Skip to content

Commit

Permalink
Merge branch 'mvella/fastq-tags-alt-format' into 'master'
Browse files Browse the repository at this point in the history
Alternative format for FASTQ readgroup and sam tags

See merge request machine-learning/dorado!858
  • Loading branch information
tijyojwad committed Mar 20, 2024
2 parents ff330f6 + 9351670 commit a0f9462
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 9 deletions.
2 changes: 2 additions & 0 deletions dorado/read_pipeline/HtsReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ HtsReader::HtsReader(const std::string& filename,
if (!m_file) {
throw std::runtime_error("Could not open file: " + filename);
}
// If input format is FASTX, read tags from the query name line.
hts_set_opt(m_file, FASTQ_OPT_AUX, "1");
format = hts_format_description(hts_get_format(m_file));
header = sam_hdr_read(m_file);
if (!header) {
Expand Down
2 changes: 1 addition & 1 deletion dorado/read_pipeline/HtsWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class HtsWriter : public MessageSink {
void terminate(const FlushOptions&) override;
void restart() override { start_input_processing(&HtsWriter::input_thread_fn, this); }

int write(const bam1_t* record);
size_t get_total() const { return m_total; }
size_t get_primary() const { return m_primary; }
size_t get_unmapped() const { return m_unmapped; }
Expand All @@ -40,7 +41,6 @@ class HtsWriter : public MessageSink {
utils::HtsFile& m_file;

void input_thread_fn();
int write(const bam1_t* record);
std::atomic<int> m_duplex_reads_written{0};
std::atomic<int> m_split_reads_written{0};

Expand Down
8 changes: 6 additions & 2 deletions dorado/utils/hts_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ uint64_t calculate_sorting_key(bam1_t* const record) {

namespace dorado::utils {

HtsFile::HtsFile(const std::string& filename, OutputMode mode, size_t threads) {
HtsFile::HtsFile(const std::string& filename, OutputMode mode, size_t threads) : m_mode(mode) {
switch (mode) {
case OutputMode::FASTQ:
m_file.reset(hts_open(filename.c_str(), "wf"));
hts_set_opt(m_file.get(), FASTQ_OPT_AUX, "RG");
hts_set_opt(m_file.get(), FASTQ_OPT_AUX, "st");
break;
case OutputMode::BAM: {
auto file = filename;
Expand Down Expand Up @@ -191,7 +193,9 @@ int HtsFile::write(const bam1_t* const record) {
// FIXME -- HtsFile is constructed in a state where attempting to write
// will segfault, since set_and_write_header has to have been called
// in order to set m_header.
assert(m_header);
if (m_mode != OutputMode::FASTQ) {
assert(m_header);
}
++m_num_records;
return sam_write1(m_file.get(), m_header.get(), record);
}
Expand Down
14 changes: 8 additions & 6 deletions dorado/utils/hts_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@
namespace dorado::utils {

class HtsFile {
HtsFilePtr m_file;
SamHdrPtr m_header;
size_t m_num_records{0};
bool m_finalised{false};
bool m_finalise_is_noop;

public:
enum class OutputMode {
UBAM,
Expand All @@ -34,6 +28,14 @@ class HtsFile {

bool finalise_is_noop() const { return m_finalise_is_noop; }
void finalise(const ProgressCallback& progress_callback, int writer_threads);

private:
HtsFilePtr m_file;
SamHdrPtr m_header;
size_t m_num_records{0};
bool m_finalised{false};
bool m_finalise_is_noop;
const OutputMode m_mode;
};

} // namespace dorado::utils
34 changes: 34 additions & 0 deletions tests/BamWriterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

namespace fs = std::filesystem;
using namespace dorado;
using Catch::Matchers::Equals;
using utils::HtsFile;

class HtsWriterTestsFixture {
Expand Down Expand Up @@ -75,3 +76,36 @@ TEST_CASE_METHOD(HtsWriterTestsFixture, "HtsWriter: Count reads written", TEST_G
CHECK(stats.at("unique_simplex_reads_written") == 6);
CHECK(stats.at("split_reads_written") == 2);
}

TEST_CASE("HtsWriterTest: Read and write FASTQ with tag", TEST_GROUP) {
fs::path bam_test_dir = fs::path(get_data_dir("bam_reader"));
auto input_fastq = bam_test_dir / "fastq_with_tags.fq";
auto tmp_dir = TempDir(fs::temp_directory_path() / "writer_test");
std::filesystem::create_directories(tmp_dir.m_path);
auto out_fastq = tmp_dir.m_path / "output.fq";

// Read input file to check all tags are reads.
HtsReader reader(input_fastq.string(), std::nullopt);
{
// Write with tags into temporary folder.
utils::HtsFile hts_file(out_fastq.string(), HtsFile::OutputMode::FASTQ, 2);
HtsWriter writer(hts_file);
reader.read();
CHECK_THAT(bam_aux2Z(bam_aux_get(reader.record.get(), "RG")),
Equals("6a94c5e38fbe36232d63fd05555e41368b204cda_dna_r10.4.1_e8.2_400bps_hac@v4."
"3.0"));
CHECK_THAT(bam_aux2Z(bam_aux_get(reader.record.get(), "st")),
Equals("2023-06-22T07:17:48.308+00:00"));
writer.write(reader.record.get());
hts_file.finalise([](size_t) { /* noop */ }, 2);
}

// Read temporary file to make sure tags were correctly set.
HtsReader new_fastq_reader(out_fastq.string(), std::nullopt);
new_fastq_reader.read();
CHECK_THAT(
bam_aux2Z(bam_aux_get(new_fastq_reader.record.get(), "RG")),
Equals("6a94c5e38fbe36232d63fd05555e41368b204cda_dna_r10.4.1_e8.2_400bps_hac@v4.3.0"));
CHECK_THAT(bam_aux2Z(bam_aux_get(new_fastq_reader.record.get(), "st")),
Equals("2023-06-22T07:17:48.308+00:00"));
}
4 changes: 4 additions & 0 deletions tests/data/bam_reader/fastq_with_tags.fq
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@8623ac42-0956-4692-9a93-bdd99bf1a94e st:Z:2023-06-22T07:17:48.308+00:00 RG:Z:6a94c5e38fbe36232d63fd05555e41368b204cda_dna_r10.4.1_e8.2_400bps_hac@v4.3.0
GTTATGTTAGTCTACCTTGGTTGCAAGTTGTGGTGCTTGCTGGTTTTTGGCTTGAAGTCTGTGTTTGAAAGCCCTGGCCTTCACAACCCAAACTGAAACTCCAGATTGGAACCAAGAAAAGCACAGTGGATATGGACAGTGGTACAAGTAAGCCTCAGGCTGGAGTCACTGGCTTTGGGTATCTGATGGTGACACCACATGTTCCAGAATGGTTGTCTGTTAAATGTTTACTAGAGTTGGGTCTGGAGCATAGAGTGAAGGGAAGGAATATAATGGAAGGTTGTAGAGTATGACAGCTAAGACTTGGAATCAGGCCGGGTGCGGTGGTTCACACCTGTAATCCCAGCACTTTGGGAGACCGAGGTGGGTGAATCATGAGGTCAGAAGTTTGAGACCAGCCTGGCTAACACAGTGAAACCCTGTCTGTACTAAAAATACAAAAATTTAGCTGGGTGTAGTGGCAGGTGCCTGTAATCCCAGCTACTTGGGAGGCTGAGTCAGGAGAATTGCTTGAACCCAGGAGGCAGAGGTTACAGTGAGCCGAGATTGCGCCACTGCACTCCAGCCCAGGTGACAGAGTGAGACTCCATCTCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTTTGGACTGTGTTCATATCAAAACTCAGAGCTACTAGCTAGCGTGTGGAACCTGGAAGGTTACTTAGCTTCTCTAAGTTTTTTTTTTTTAATCTGTAAAAGAGGAATAAAAGTTTGGAGTTAGGTGGAAGTTATAAAAAAAAAAAAACAAGGCTCAAATTATGTATAGAATTGAAAAGTCCAGGAGCAGTCTGGGTTTCAGATACGACTTGATCCGGGGCAGACCCTTTCCTCCCTGTGGCAAGATGGCGTCTTGGTGCTCTAGGCCTGCAAATCTTACCCTTTCAGTAACCCTAATAAAGCATGAAAGTATTTCTTCCTTGCCAGTACCAGCGAAAAAAAAAAAAAGTCCTGAGGTTGACTCTTGGCTTATTAGTTGATTATAAACACTTGAGTCAATTGCTAAGAACTGGGTCACTGCCCAGCCCTGGAGCCAGGAAAGGGGTCAGCCCCACCCGAGCTACAAGAACAGACAATAGCAAAGGGATGATTTTTTTCCAAATGAAAATAAATCATGGTGCTAGTACCAGAGGAAGGGGGGATGGATGCTGGGCAGGCCAAAACAATAGATGCCCACTGAAGAAGCACTCCGTTCCAGGTCATCCTTGTTAATAAGGAAGTGGGACAAGTACAGGAACCAAAAACACTTATTTATGAGGATCCGGGCCAGGGTCAGGCATGGCATCAGCAACTCCCTACCCTGCCTTTCTACACAGTAGCACAGTCTTTATATGATAGAAATTTGGTTGCAGCTTCAATGTGACATACACATGCTTTCAACTCTCAAGGCATCAAACCTTGTTTAATTACTATTATTCTTTTCTAAGGTTTTGGTATTTTCCCTCTGTATTTCTGATGTGCCCTTCTGGCTACAGATAATCCAGATAGTGGTTGTTGTTGTGGGACTGTGAGGCAGGGAAGTCCAAAAAGTGAGGCTAACGGCCACTACTGACAGATGAAGGGGCTTCCTCAGGGGCAGAGGCACAGTGTCCGGTGATACAGGCTGGCACCTCGAGAATCAGGGATGGGATTTTCCTGGGAGCCACAGGGTTCATACTTGAGGGAGGCTTGGGAGTTTTTCACTCTCTGCATAATGGGTCTGTTCCCCTGGGGATAACCCACGACAAGATATGCCTTGTGAATGTGGGTGGCAGAGGGACACACAGGTGCAGGGGCATCTTCCAGCCCTGGACGGTGCCACATGAGGGATGGATGTAAGACTGGCCATATAGGTGAAGTGTCCGAGGCTCAGAGAGATGGCAGGGTTCACCTCTGGACAGAGCAGGACAGAACTAGAATCAATGTATAACACCGGGGAAAAGATTGTTACATGTAGAAATGCTCCACACAAACACATTCCAAGAACATGAGTGAGAGAAAGAGATGGACTGTGCTTGGTGGTGGTGGTTCGGTGCACTTCCCTCTGGGTTGGGCTGGGCTGTGGTGACAGAGGAGATGGGTACAAGGGAATTATGAGAATTTTAGATGCATTGCTCAAAATTTAGGGGCTTGGTGTGTCCAGACTTTGATGTGGGATAAGAGAAAAGGAGAGCCCTCACGGCGGGACATAAATGGGTTAATCAGGTTGGGAGAAGTGGTATCCAGTGGTTGGGCCAAACCGCCAAGTGGGGAGCCTGGGTCCAAGCAGAAAAGACAGTTTCCTCCTTTAGCAATCAAAGGAGTCCAGAGGGGGTGCCCAGCCTTGGGCCAGAGGGAGAAAGGAAGAGGGAAAGCTTTGCTCTGAGGATGAGGTTTAGAGCAGAAGGAAACAGAGACCACCCAGAAAAGGGAGACTTTTCCTGTGCCAAGGCGGAGACCCAGGGGACTGTGCACAGTTATCTCGGCCCTTTGAGCGCCTCCGTTTTCCCTTGTCTGTGGTCAAGCCTAGCTCTGTATTCCAGCCAGCTGTGGGAGGATGGGGTGACAGAGTGATGCTCAAAGAGAATGTGGGGCCAGCAGGGGCAGCCCAGGACTCTGGACTGAGGCCTTCAACAGAGAAGTCTCCCCTCCCCTCCCTTCCCCTCCCCCTCTCCCTCCCCCTCCCCTCCCCTTCCCCTCCCCCTCCTCCTTCTCCTGCTGGGAGTTAGCTGGAGAACCAACAGGCAGCATTACAGAAAGCTATAAGGCCCCTTCAGCTGGTTGAGGGGGCTCAGCTGGCCCCATGGCTAGGGCATTTGTGTCCTGTTTCCTGCCGTGCAGGAAGAGGGGCACTGTGAGGTCCTCCCGCGTCTCACCCCAACCACATACACACCTGTGAACGATGGAGCAGTCCAGATTGTCCCAGCCCTACCTAGAGGAGCGATTTGTTCTCTGATTTCCATAACACAGAAAAAATAAGAAAAAAAGAAAAAAAAATCCAAAACGAAAAGTAAAACCACTTTAAACAATTAGGAGTTTTGTTCGGTTATTTGGCGAAGGCTGTGTGCTGGGGGAGTGGGTAGTGAGGGAGTTCTTTATCCCTGGAGAATCTAAATGAAGGAAAAGTCAGTTTGAAACCGGCTCCCAAGATGACGCAGGGTCTGAACCCAGAATAAACTCTGAAAGCTATATTTTCAGCACAGAAAAGAGGGGCTTCCTAATGGAAGCTTTGGCAGCCCTTGTGCTGTGGCCCTGGCCCTGGGCAGTGCTGCGCTGCTGTTTATTTGAGAGGAAGTGGTGGAGAGTGGTCCCTCTTTTGTGGCGTGTGGTTTTGGCAGTGCCTGGGCTCTCCGTCTTCTGTTTGGGAGTCTGGCCCACCATGGAGCCCTTGCTCTTGGTTCCATTGTTAAAGGATTCCTGCTGCAGTGCATCCGGGGTGCCCACCATGAGATTCCTTTGTCGTGGAAGAAGGTGCCACCCTTTCCACCTGCCTCTTTTCTGGGGGGATTTTCTGCCTGCTTGCATGGGAGGCATGTGGCTGTAGGTGGGGAGGGCAAGGGGCTGACTAGAAGTGGAGGTGAAGGGTGAAGCCACGGAGGTGCCGTGGCACTTGTCTTCTTGGCCCTCCTGCCTCTGAACCCCAGTGACGGTCTCTTGCGGGCTGGTGGCTCCACCTTTTGGTCTGTGCTGGGACCTGGCAGGAAAACCATGCTTGGCTGTGTGAGAATGGCAGAGTATGGTGGGCCTGGGGCAGAGTGGTGGTGGTGGCAGAGGAACGAAAAGGATGGTGTTGGGGTAGCCATGGGAACGCCAGCTTTGTAACAAGACAGATACGGGTTTGAATCTTGGCCCCAGCACTGATTGCTGATGACTTTGGGTAAATAGCTTGACCTTTCTGAGGGCCAGTTTCTTGATCTTTAATACGGCCATAATCATACCTACCCCAGATAAAGGCTCAGGACCTCTTGTGTCACACAAAATATCGTGTGATTTTGAAAGCAATGCCTCGGACTCAGACCTATAGGCCATAGTTTAGGGAAACCCAAATCCTTCTCCAGAAATAGGGCTTATGCTCATGTGGAGTCCTCTGTCCCAGCTACCAATTGGTGCTGTAGCCTGTTTTGCCTCCATCAGCCCACACTCAAAACTCAGCTCCTGCCCCGATTTTCCACAAAACCCACTCATAGCAAGCACTTTGCAAGCTTAATATACCTTACAGACAATCTGGGGATACTGAACAAGCAGCTTATTATCTCATTCACTGTTCTTTTTCCTCATCTTTCTTTACTCCTGTCCTCCTAGATTTCTCAGACTGCCAAATTATCCCCCTCTATGCACAGGGCAATTCAGCTCTCCCCATGTCCTACTCCCAATATTGCACACCAACACTTCTAGAATTGCTTAACAGATTTCACCAGATCTAAATGTCTCTAAAAACAGTGGAATAGAAAATAACAAATCTACTACTGATAGTGCCTACTTCATAGCATTTTTATGAGTAATACTATCACCACAGTGACTAGCACATGGTAATACTATCACCACAGTGACTAGCGCATAGTGATCAATAGCTATAACCATTTGAAGAAACCAGGGGTGAGTGTATCTGAGAATCCAAGAAAAGATATTGGCACGTTGGTGGATCAAAAAGCAGATATTGGGGTCAGCATATTTTGCCTTTAATCTGACCAGCATTTCTACATCTTGTTGACACTTTGTGAAGTGGGCAGGACAGCCTCCACCACACCCTTTATACAGGAAGACAAAGCGAGAACTGCCCAGATTCACCAACTGGGAAGTGGCGAGTGTTTATTATGGATCAACATGTGTAAACTGTAGGGGGAGGGATTCATGGGACAGAGGGAGAAGTTGATCAGCAAACCCTATTGGGAGCTGTGGAGCATACGCAGCCCTCAGAGGTGTCCTGTCATGGGTCTTTGTACCCCTGCCACTGTTAGCTGTTGCATTTGGGCTACCCGGAAAGGAAAGAGATGCCCTTGGGCAAAGCAGCTGTCTATGGCAAGCACACTCTGAAGGAGCTGACAGCTGGAGGCAAGTCCTTCCCTCCAGAAAGGGCATTTGGGCAGTGCATCTCCTGTCCTACCACTTTCTTCCATCTGCAAAATGGGGATCATGATAGTACCAGCTTGCAGGGTTAAAGTAAGGTAGTGGGTGCAGGTGTCTTCCATAAACAACAGTTGTCTTTAAGGGCACTGTGGGTACTCTGTCTACCAGGCAGCTCTGGCTGTGGGAGCCCCTCCCAATAGAGCTGCCACCAGCCCTTTCTGATAGGACTAACTCCCCAGGAATGTCAGGGTGGTGACTCCGGAGCACTTACAATTGGACACTGTGAAGATGATCATTGTGTTGCATCACCACTGCCCTTCATTCAGTTGTTTCAGATTAAATTCATCATAACAAGAGGTCTCTAATCAGAAACACAGCTGAACTTAAATACAGGGGGGAACTCTGGAAAAAAAGGAATGCTGAAAGAAGCTGAGTTTCCTTCATTCTGAGGACTCTGAATACATTTGAGACTTGCATCTTACTCTTCTAAAGCCATGCAGCCCAAGCTTTCTATTCCATGTTAGTCAGATGTGGAGTCATTTCAGACCAAGATAGAGTAGGGGTAGATAAGATTCAATGATGCTTGTAGAGATTATCACAATAATAGCCAATAAATCATATCTGATACCATGCCCTTGTGTAGTGTTCTTCCACACTGACTCTGGGCCTCACCCATGTGTCCTGTTTTGGTCAGTGTGGCATCAGCTAACATTGACCCAACAGAGACTGGTAAGTGCTTGCTCACCAAAATACTGAAGCTCCAACTGGCCTCTTGAGATCAAAACCAGGTAAAAAGAAGGACCTGCCTCCAGCCAAT
+
"','((('$$&$%$$%&*'&&&&%$%')+)($#$%&%$#$%$$%%%$%%-:;<:;??A;;46+)587;HMLOLFI>>>CJLFEFFGKNRRSSPRRSRMIG;9076111=AGD?=5B=1-.ECDEHHKIF>>;9567:;9985&$$###&$#$&,-)'(,(53003;65;DFHPOHIDC>;5&%&'(9=>GCDCDKKLLNMJRH5F5HLROOOMNOOKHAB@;?L;8H1001D?:9=8756>>431101;57++++,/-35>@ADB;AAA:7666@DDFKHKIDKGEFDEEEHHNIIDBA>>?@9411>DMIJIJLLMRSRPRKKKKI::::MMMMSSSNRRLRRSRSSRSSRRRKPSSSOSRSRRQSPRNRORPSRKILLR?GKJKDJMDCCCJPPMRSRRRRSRRPROOLORMRSSSRRSJI<74332669LSHI?@?AFFB9774?ABEFIRSOKKKKKOKLKKLOORKMIJKLMNOORRLJOOKRRMROSRFHGGDH>OSRRSSHGAIIGDPLDPJRNKMRSPOLSGROEEEFSPRORNHKLNRRSOLLMRSRRRRSKRRSPLFEEDEHHLJ>77@B1111B?B@:JJII>7938KORORORPOOOOORRROOONOMOMSSSRRSMSSNROOPLLHE?=@@B@>;::?10.-//1011122222433123217:;HEEDFJOOIOJ:IJIFGBCD8FFECBDFA@47FHLMOOKC??654...6DEBICBGCIPRSRLBG8..29:01246;=EDCCBEA=@>RRSSSRRKDE>AAAEC755<<GFFECDDMKLLIHHELOMJEA@>D;MMJJMOLKKKKKMOPOLLJIHEC9:2((+*)(&')(,,,+),,75.@;;ALLLRRRRSSPOMBCCKONOMKMNMMMJH>>>@EIILDDFLCB>3573;;A<DFIJONORROPRMOONMLLMMLJIJIGGCBECLRMMJLLILONMFA8677:;CFGKSSSRSMKKLLLMOPOMMNOSROOMAAAABEEA''''',,,001EJKOLMMNPRRHJIHHCAA@800BCEA??>544400<AAB>>BH;504121=B=@>ABCDFCBBCMIGHKMH@AABEBGG>::;99;;;<DHGHHFGPOK291((((--.:FCB;HJF?B;LLPOMNFMRPPOSPOOPPPORDB@AKKDIC@AEGCB=6/-+--77:?@@BB>1&%&7>KJLJKLLLONLJJJIKLLKLLMMMMC@33.-0*EFG@<<>?FEAA;8658@67796532232)%$####%(.4045BHMNGLHGGELDNLM<<>BCMLHCHKI=?:50-)))*+.0&&&+>98934DBB@?@A?<==FORLIOPNOMMOMIMMMRROMLKLHMOPQRNKMLIIABNRSSSPRMNNPSORSNJJKLKMI5444641--5>322GGJIJKKIHGHJORRROLONSGORKBB??GIMMHHFEHDCE5/,.-,,&&0@MORRSOONOERRSHB?GGMMJJDKGE44445153,'*',))@FGE>===>BCCIAAA<>==////?((((31/))'&&&%%%(.2/1:;=EGEFFJJLMRORJJJLKKOOPKIIIMOKOMKLMORSRNOGLKFKGMFFFFE@0//17HKLFLKKLFFFFOPRPMOMMLLKJLJMSOILLNLLHHED<:<974457DBIDCCHGFHJIJFBDLSF>>?OLLKKJLOPOLLNIDFFIJKSKGICAD<A@==>KA;:>DHJFD@??@A?9@@BDEFEELACCGHCKLSPK:99210-)))3356545>=>AMJLHIIMOOOMMLMPOPRMOFNPLILHIIJMI=@549:@:99DCB860<KRPOMKMCA@@AKJHHLKDCDEDDGMIIIFH0///7567:HKOKMFGGILIOMSLRORPLONKOLEDDDBNOLIIHGGGGEIHCIIIKIEDB;84434>BJIEE<899911276))))<F<;88::F4-0:BAJCADACEFBB@62210(()48==B@::9@MIGHGEMMKLKILJHIKMKIJBABC=62006>EFJIGHFLLROJJFDBA=6@GFFEEE988400156<9794.000BBDHLOOOONKOIIJJRRRJHGFFFF=>LIDIIIGONOGE92115355434324@BB<DC666CEFFKMADC5321579=ABCEIGGGCEDCKDHGFFFFEFGLGNMMMKONKOI:87855@AHFFHIIJIKM----->>>>CB?@?@GGBGGJKIFJ64484GDIGE@>>;;,.&'''(('&(((((##$-,.0-***./<=@JJHHIJMJG<<==CE887445:<DGHIFEFFEHHCA;7897//../17>?AFGMJFA>8A@GLHHHGFFINOMMOONIKLNBIHFEED@EEAA@9980.-/97/.-..*,*.=?CFFRSPSROJID>B5//85556;CGKOD89B?>@@BDA@<<HADMJK?66962279:8A6AEHIMKDHJMMJHEDBDILMKMLKJILOLKIH<;:8/.+*)&((<<??5.--.79FGFEBB=CA?8/)A=>FFFFEEB99999KKEEOMLHGGFFHIRMORNORSCKKSOGEOFKJBCBGGFD=4**)*867((((=:9=CCCDGJMPMMKMOFFF<;;;BKMJKGHDEFDEEDFGHFFKJJNRRPMOC;;;;A?>>DDCHJFDGDD63C?>:;HC513DCD;986?>997:=A=<86CECCD:978A=E912DCC>@EAJLJIHLKEL?FEFDIOOKRSRKJF?;<C78DFJJIEGFFGKIMBBB<;;000067697811)&%%'09:;601BEMFEFFIC??@DIII51115989=CCCCAAAA2--/4654...40---BA;B=CDGIB@A?@530.*''')21+)'()-75667>@@=>96A@ADCEEEEEGFFGJOOMKIIIIDFFECA&&&&*4333223343+*)**%%%%&%'&+-/37++--1129EKKG----LKMKKMLHSPFOPGRFHIIHJRFFKLOMECB400((*>CEGD?;DBKORMJJFJKKRSM>>>MSRKIFGHHJJFIIRMRPPDCB6149:EFFFMKMKGDCBEFIJRLMEBBCIMHHGGB=942357IFEAA-444999856<95:;:42396;:<?@@@IJKIHHI3226ADDHJIORROM><<<CB641??B>>>@MMF;;:9;+++**&&')/,,,,27?@ABEEEHHHJMFHILKLJHGEJKIIKG.----9743326?EEDHIGPOMMHGHKBIJNOJIILFOMKNECBCEEGLJKLMNJIIFFCCGJHG?@CE>>>><>=>BBFHJKI<>KC@BA2/-++/,*))))7@B@CB?@66:;?=?973/..AEC?@@ADFIFFFHGMMKID;;;<EE5-HHIKJGHGJOLJHAD>:ADLHIHGJJOLLIHGFIHDFAB>=A6--A;;40.-*'(%)545537AKNLHLFOMOOOOOLMMRSSSSSKOPRLELRRPSPORJLKNHHGEJRJDHHGMONEORRRLOOLLMLOSRMLPJRFJKJKIBF65598789:BSOICDCLNM:::NOMFFA=?KJKMFJONKIOLRKJKMMM4222/14A10024D=FLIJHE211799<>KLMNIHGBBEEELLKKGEDD?=8**+8GHIHHGD6GHFEB.....@=>@=@KOPRKJHPSPINLNMLMNRLMMMOOLOHFGMKHMGLIILIOPROORMIOMFJG=9877DOMROPRJOCC;7@?A311.,,-459987444A@?@KSSRMF=<=CLPHMLLRRSROOOPRGMSPMI667JJIBBGGGJFMORRRRSRRRSROEMPRGLCRNORRSSRRPO=;;;OMKIHFGJEE@HC?=6333//03/568:DEFGICC@AFE:::GONIOOKFKD7AFDHIHMLMLL?@A?EBA422841,,,**,GHIJKFEEEIIORJHOLAIGGHMSOHSPORSLONGORPRANLOOGGGHKJJLMOOCBBBIHHFFADDDDLLMRRRSNMA@BCROOOPOPLKIFMMOOJJLNRSROLLOORNRRLROHJORRRPRSPLFIHLRRSSOKEEEEGLLHIJJRMM.....(&&(388=<;<=ENOOOOMONNMOORPOSIDCCFJGJIGJ??JKOECFFKLMOKJKLEDBBOFFEGRQMRRRRRNRRPSKIHGF874888=@@0.*?0//7=AFGHGOMMLRSSSMRSSRRRMOMOMLGEDEHOOI@A@@?BHHHIIHGFFSSRPRNMMBAARMLJKKKKJ@@@BG?>1/1(CIKOPLHMPRRRRRROCCC3334OOOOPOOROHHGHROM----CJJLFFECB>HFIEIBFHLNPRPMRSSNLKLKROOLKIMLOMKJIIIHLEEMLLMKLG@>67:))'')*678779GIMKIIE>....6)))))(,,,334DIIJKROMOGE>:HBF?=9:HILMNNOPLOOMKIBBMSROIFC0002HECB?4/9ECBB@==C@AC?@KEECDDDKOOOKKRNKKNMNFEJSSRLRSISOSOPOIKJIOOORSSSSRQSSLKGDEKJHIKLGDJOOPDCCCIMSSDDCCA@@@>EIKMDCCA<<?@EIJFFHIFGGGGHIIHMLKMRRRPOOOPJJHHII..../EBEHMNMLMLONOLIILMNKODORRRJMFEIKJJNONMMJKKE@@@GIFDA>=>GKMRPMECCJJHSRROJJIDI?<;::.'''AFGHKMOLKHIABBDDE=999@<9:896698?1/88+*&&'(-4?@AFHGOIHGHC;88LIADKMIC@PKRPMMMHIJKFECA??=;;;<AFHIIIKLJH4:;F<FGLKKLLOFDDA9675/)%$&(**+<>AGGIKJGKDIIILFOORRRRPOKHGGJIBBBBHHJLLKJKLOORSRPRMOMMOJICD579DF@?<<<:0*(((,69>>=:875+-,*++,-*+--AHIDEFDFCB54446DL>98:B<5((((244;=GHGFILKFCCJJG@E:9996++,-/;E@?AGCJHBAOORGLLJMOIOPJJIHELROLBMPOORRNOIHIJHBCFORKFEIMMIGFGLMIID>>ONMLLLRMMOMOMHGEDGGOMHFFFFDBC>;:99==AAABCDDDGIH@>CLIC;;;;DC:0--=7@A.FLLOOOOOHOANLMGHJIHIIJMFFEEKMNMLMGGGFEEE1/22()''('&'(')),75??CA>===AB99:9:=::::6-@?@ILMPMIIC?6556DDIIIKMMPMLLMOLKIGIDE>;669=:997882.///11-5?FLMIGGFGDE@@DAA??@@BBDDMKOMLLONOPMKLOPSRRRMRKDDDKMCED@D;)((*)*...--,)'),.+03-779=-,,--:1003++-018?@EEDM<:<AHIHEE?<;988:@BFGMKKJGMMLLNKLLLEDC::A@@?EKHHHHMMORRRJMBMLLHFHH=>@@JHIIMGIOMNMKKLH<:D7333CDB@@AF@>90489;B<97;@??=?99**)%''&&(&(*))'&%'())'&&(.++*,..3<:9-,,-,,-049@GGHIAFIIFFE@HLKGRRLMLEKFCGJC895'+***1<=EFDEJIKHGHGBBAAJCCHDC>>A?BFGGGF;9765:7633LKNLLKNMJKLML4..-./7))'*(((/0---)'(+***-''#$$''&'+,.('&%%')%$%&$##$##$%')+)((('&%%'()-00488532-,,+*.0178;;:89556*((%&%$$'*'''('''$$%&*+/.1108337543(776545346174&)696462222*())012-**+,,-411((''/06777222+)((),//../+)))($%%&-,$)))-)'$%')))*+***''&'--+(%&('))*'()+*('&$&()))&&&',.(&%$$$%&%&''('('(()+*+/*(''+0.(&%&'&&(((('//,050./.

0 comments on commit a0f9462

Please sign in to comment.