From 6bacb41abb1b4468018325ec4cafc4c79363b34f Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Thu, 25 Feb 2021 07:09:25 -0800 Subject: [PATCH 01/71] implement a simple ZipFileLinearIndex class --- src/sourmash/index.py | 44 +++++++++++++++++++++++++++++++++++ src/sourmash/sbt.py | 4 +--- src/sourmash/sourmash_args.py | 25 +++++++++++++++++++- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 8dd4069f04..068632878e 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -2,6 +2,7 @@ from abc import abstractmethod, ABC from collections import namedtuple +import zipfile class Index(ABC): @@ -159,3 +160,46 @@ def select_sigs(siglist, ksize, moltype): siglist=select_sigs(self._signatures, ksize, moltype) return LinearIndex(siglist, self.filename) + + +class ZipFileLinearIndex(Index): + def __init__(self, zf, select_ksize=None, select_moltype=None, + force=False): + self.zf = zf + self.ksize = select_ksize + self.moltype = select_moltype + self.force = force + + @property + def filename(self): + return self.zf.filename + + def insert(self, signature): + raise NotImplementedError + + def save(self, path): + raise NotImplementedError + + @classmethod + def load(cls, location, force=False): + print('XXX loading', location) + if not location.endswith('.zip'): + raise Exception + zf = zipfile.ZipFile(location, 'r') + return cls(zf, force=force) + + def signatures(self): + from .signature import load_signatures + for zipinfo in self.zf.infolist(): + # should we load this file? if it ends in .sig OR we are forcing: + if zipinfo.filename.endswith('.sig') or self.force: + fp = self.zf.open(zipinfo) + + # now load all the signatures and select on ksize/moltype: + for ss in load_signatures(fp): + if (self.ksize is None or ss.minhash.ksize == self.ksize) and \ + (self.moltype is None or ss.minhash.moltype == self.moltype): + yield ss + + def select(self, ksize=None, moltype=None): + return ZipFileLinearIndex(self.zf, ksize, moltype, self.force) diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 9cae16b693..7c3a0856e2 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -696,9 +696,7 @@ def load(cls, location, *, leaf_loader=None, storage=None, print_version_warning if storage: sbts = storage.list_sbts() - if len(sbts) != 1: - print("no SBT, or too many SBTs!") - else: + if len(sbts) == 1: tree_data = storage.load(sbts[0]) tempfile = NamedTemporaryFile() diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 258b99cee0..d771e294fa 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -16,7 +16,7 @@ from . import signature from .logging import notify, error -from .index import LinearIndex +from .index import LinearIndex, ZipFileLinearIndex from . import signature as sig from .sbt import SBT from .sbtmh import SigLeaf @@ -322,6 +322,19 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) filename, end='\r') n_signatures += len(linear) + # zip file full of signatures + elif dbtype == DatabaseType.ZIPFILE: + db = db.select(ksize=query_ksize, moltype=query_moltype) + + if not check_lca_db_is_compatible(filename, db, query): + sys.exit(-1) + query_scaled = query.minhash.scaled + + notify('loaded zip file {}', filename, end='\r') + n_databases += 1 + + databases.append((db, filename, 'Zip File')) + # unknown!? else: raise Exception("unknown dbtype {}".format(dbtype)) @@ -351,6 +364,7 @@ class DatabaseType(Enum): SIGLIST = 1 SBT = 2 LCA = 3 + ZIPFILE = 4 def _load_database(filename, traverse_yield_all, *, cache_size=None): @@ -434,6 +448,15 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): except: pass + if not loaded: # try load as ZipFileLinearIndex + if filename.endswith('.zip'): + try: + db = ZipFileLinearIndex.load(filename) + loaded = True + dbtype = DatabaseType.ZIPFILE + except: + pass + # check to see if it's a FASTA/FASTQ record (i.e. screed loadable) # so we can provide a better error message to users. if not loaded: From 61245eb75544f246be68d1881f9ab6f4ee95a3b3 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Thu, 25 Feb 2021 07:15:33 -0800 Subject: [PATCH 02/71] fix load_file_as_signatures --- src/sourmash/index.py | 3 --- src/sourmash/sourmash_args.py | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 068632878e..912e91413b 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -182,9 +182,6 @@ def save(self, path): @classmethod def load(cls, location, force=False): - print('XXX loading', location) - if not location.endswith('.zip'): - raise Exception zf = zipfile.ZipFile(location, 'r') return cls(zf, force=force) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index d771e294fa..f249c7db8c 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -535,13 +535,13 @@ def load_file_as_signatures(filename, select_moltype=None, ksize=None, db, dbtype = _load_database(filename, yield_all_files) loader = None - if dbtype in (DatabaseType.LCA, DatabaseType.SBT): + if dbtype in (DatabaseType.LCA, DatabaseType.SBT, DatabaseType.ZIPFILE): db = db.select(moltype=select_moltype, ksize=ksize) loader = db.signatures() elif dbtype == DatabaseType.SIGLIST: loader = _select_sigs(db, moltype=select_moltype, ksize=ksize) else: - assert 0 # unknown enum!? + raise Exception("unknown database type") if progress: return progress.start_file(filename, loader) From b22248b2b8dc8c0a0a97172fb1bdd12cb5f81bfc Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Feb 2021 05:53:10 -0800 Subject: [PATCH 03/71] add tests for zipfile searching etc. --- tests/test-data/prot/all.zip | Bin 0 -> 193111 bytes tests/test-data/prot/dayhoff.zip | Bin 0 -> 71522 bytes tests/test-data/prot/hp.zip | Bin 0 -> 47919 bytes tests/test-data/prot/protein.zip | Bin 0 -> 73714 bytes tests/test_index.py | 84 +++++++++++++++++++++++++++++++ tests/test_sbt.py | 9 ++-- 6 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 tests/test-data/prot/all.zip create mode 100644 tests/test-data/prot/dayhoff.zip create mode 100644 tests/test-data/prot/hp.zip create mode 100644 tests/test-data/prot/protein.zip diff --git a/tests/test-data/prot/all.zip b/tests/test-data/prot/all.zip new file mode 100644 index 0000000000000000000000000000000000000000..989c9448e27f22ed565475304daba538f51e9931 GIT binary patch literal 193111 zcmV)tK$pKzO9KQ7000000IPdXQUCw|000000000000;ma0Ayi#Xm4g_FI7|t00Ytk zD`0{KD`0ha3jhHG_W=L^1QY-O08mQ<1QY-O00;o9drwj!*xd(6bN~R;?f?Kb02}~h zVR>k8W@ax(LqT6KFflbbGdVIfE-_z0Q%x~7IWsvjb}?UYa&L5HX>KlNVPP(3dM?mn^Cw~ATBjAF!y|M~y?%isUgU;pjj{_=N! z`L}=l_y7LSfBm=r_Fw+(AOF{X`Ro7q_y7L4zx@94w}1ZYKmODF<^1u#`MZDk_ka2O z|M8Fi`Y$6|{?k9t5B~kXU&s9AKm6lA{q0}=`pwo#5 z{vZGM??3+c^}qbT{`-t;Y zdwI6!Ubf}g=fAi0+}`DR?{(jw<^65jv7XCz9NT-n_w(EK=eo9ieYfk`&f~Ye$2~WD z_IH`TK7VuJxnJA4-q&_->+f9V&fB}*_j%7-{;s*v{Oz{9@3p<}?|S!jzm9$Ga6i}f zyVvbH&*Ri+j7q*ZR_@XpZi_TeSUnd>$}hQz4M28 z$r*&}Ugv|i?Vh)L=KjZfUdITo8I=88p5?iZbNQ|NyC2uH?*{0(@85dtGiJ+uE$6eX zesavaUgvQg%e==tbv>T*oyXnRbuPy;Pr0_|nh!hXRi2rP-+J#eX!DLU%I~qC1P#qS z7v0Y~Z#pA#&TW=u1luz=y{~)T&GF6)&(JOh!9J5X zFE+!mZu2cOvGeQs`3(O3JTsp&`1`&t=IpuGYXtj#%p1MyH7jLqI#V%ETxO7;Z6@cO zCD1>!o^G!;_n5I*49{}E&vnl|_G?ziX_l93-{vPXVY85CfMys*{F^UbjMjVZ$GN)c zeCWLAJbkA1@*dZG_`ROj{MS35J%VGO$@JW1K6V82r}LPlIdeM0JU^M?e&+A?b;igL zZuczHV%V5{mgS`;MV8dAM5qK?^z$mIbSgwWhQnzXO&;O zoiWp}z0WL@Yjv0Pv?bnmE(^m(ZperHV2ZC27u!z_$>OwTpD_c7=1Jp6a8eg6!r zZ8o&d&3d^ON27pDljOU##=$v)Jas_qfi-z8JwZ^E%qY zq|BP1d(4#0f1bxSBlCL7jNm+GE`Hu)opn0fU`FwpiMwW#%)Xs{wcmzpM(CJVBDjpk zth(9RGjqo~+kB@0=94!!edn!a6V9JUNzbA?8iu*)Jug2SX*AmD`=9+Wk#p10X0r-5 z+u?kV`N;@Q?|#nu_EjU;XLVC$*FK79AHiW?ud|&`OZ7)vo%6s^zVn~6_~#ijRkJZi zTg^V5dz_6v1qRx!3QUl|e(yc9<8OnH#0C&xkCe%4eAz^QO<* z+8OO`W6VCCU!M-&$I0WqjR^>pVwj&jbJwIsG93A zLht&UT{ROkhr;~fezwu^vtnl>%yVaR_&9<&KxRznl-Z`&KKsobW>?Qia?LR@FX^D6 znP;*6uG9H2XVGk`dwx8EV`gJ6I_3ptSVu75I{N5-=d(wljo|T_qYw@&W?pO-{Ah~V zM>9gBvYuCR00b(`fq%5c7AK7FQo zyIRMilbvX%oiP8*JI#?cDr-K)bXgDQ2xfd|JZ9@J-f#}Redc~few+VZU9rvsXUx6! z49oHxeLoL5=FMky&rpou8nrOnZ?IZUUTlvp>ok5vm0lX%`%#QM#0QYXN0$z z2j}e^{ujY~-rQ&QJKgo037n6cV`|pr^_%8esN3EMrn+d;utcqF3j;Gln zo14y%pR*>s?dcx$;OuvUF}h?O!9mB(05T}fdG%SRvxdCI=_DhVw{QZF{#<7o9*S*C zL(Rv|%smFd`#<+6iCM{`%eT#eHQIWPi5Z}qQ8fE<7TqlHd5>9s&VIJj9E3YTs(x0& z7!~*Oo5eW8KMHl`X4LdLg88y-Rw9i$cIA(HdG>ja%aOzSny=l)NSSx>xc4{jJO49y=${jQO=NPv#IDlg@W-sY*MZjW>5)=ryZ| zz+-1j_T}*^zjt1BHuQ|s?3~dTBNzkFht0N``5$YGnKctT3voA{V>=nRZPdxk+q~W= zP?C+IFq>%3@lm>?TjxNT5tzj~6ETA{NAY~;P6du~e!9<0^sFBTEKBYpd1eOZr!yD! z`Oi4}J}2zVE8A|l=Cl~A+$X)x**Q690r|^?^?bO-WUz3omf2-L`gIo4nsvRiXGSt> z;hNLtp;LGFVG}b+X8epkN%OKgFt6;_u^t`&dqaOSEk`t(edc}sZ!AZif^(BqJ7!O| zg3*~3LNYqWvYYRjy*10?=q#FJo8%q+F`qUk_qlY9t+&r6uz-F0jNB|J#^7kG#q6x} zq1=*ZR91cj$!x6oqItzpGX2U3&kK$Nz;^vnjk6nO75ns~`^>CuYs@_xKxm^1kP2v6LKV@oJKFrVLu0p_t{1*=kzf5DCeeinO$=78fPuf z%*~NElDS|^_ub(*Z$vU$`J#kJw{Av*8la?3PS&jBk<9gTd|P_w%RX7>{FxQXyk@O? z!%-a$lzEr&6Gk)=?>iIWNS*u7w~vPMuB+p9Wn9nMcv7mfq33Sxl%0Z{?;KNb6#N(z z&d-A(J1c6=vX@gg_nr5i`I))B?ZKU{w3#?5uNAdh#cb1A!n5dSPMr`lG_!6^8~{(rk>PTjd^OodrhWAV&Q=gebl&Bu*O&ZnF`^x6rmq&YfB z#+93mHHWWNJd#lkvrA3%#>FFuT0AbIGqxCN01H za>s>aywb4)X1GVaAKv+7!;X#}?R_*pR^RBxnW5Y$*NhgN6~@iX&Ca=4sXw21XNlS@vmZ#t2cbvi*7MsW?tJh=N55VR$t-k#J}B5Z zwr134J&rbd9Hg%iD}He1nvavU�cxU>aafx25@N3(l&XbvWzuNV4+{ccU_U&Kn*= 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 z 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 literal 0 HcmV?d00001 diff --git a/tests/test-data/prot/dayhoff.zip b/tests/test-data/prot/dayhoff.zip new file mode 100644 index 0000000000000000000000000000000000000000..e9aedbcaf70edaea545627a70a85ee5d32b04076 GIT binary patch literal 71522 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�cxU>aafx25@N3(l&XbvWzuNV4+{ccU_U&Kn*= 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

ah)&Af~7ABLdSPEDj?WYSf^Cx$;9xW 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 A!~g&Q literal 0 HcmV?d00001 diff --git a/tests/test-data/prot/protein.zip b/tests/test-data/prot/protein.zip new file mode 100644 index 0000000000000000000000000000000000000000..3103c0217caaebb83946b9c0baed00a1068d1087 GIT binary patch literal 73714 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 literal 0 HcmV?d00001 diff --git a/tests/test_index.py b/tests/test_index.py index 1313162a2e..d1d3e3a9f1 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -393,3 +393,87 @@ def test_index_same_md5sum_zipstorage(c): # should have 3 files, 1 internal and two sigs. We check for 4 because the # directory also shows in namelist() assert len([f for f in zout.namelist() if f.startswith(".sbt.zzz/")]) == 4 + + +@utils.in_thisdir +def test_zip_protein_command_search(c): + # test command-line search/gather of zipfile with protein sigs + sigfile1 = utils.get_test_data('prot/protein/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') + db_out = utils.get_test_data('prot/protein.zip') + + c.run_sourmash('search', sigfile1, db_out, '--threshold', '0.0') + assert '2 matches:' in c.last_result.out + + c.run_sourmash('gather', sigfile1, db_out) + assert 'found 1 matches total' in c.last_result.out + assert 'the recovered matches hit 100.0% of the query' in c.last_result.out + + +@utils.in_thisdir +def test_zip_hp_command_search(c): + # test command-line search/gather of zipfile with hp sigs + sigfile1 = utils.get_test_data('prot/hp/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') + db_out = utils.get_test_data('prot/hp.zip') + + c.run_sourmash('search', sigfile1, db_out, '--threshold', '0.0') + assert '2 matches:' in c.last_result.out + + c.run_sourmash('gather', sigfile1, db_out, '--threshold', '0.0') + assert 'found 1 matches total' in c.last_result.out + assert 'the recovered matches hit 100.0% of the query' in c.last_result.out + + +@utils.in_thisdir +def test_zip_dayhoff_command_search(c): + # test command-line search/gather of zipfile with dayhoff sigs + sigfile1 = utils.get_test_data('prot/dayhoff/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') + db_out = utils.get_test_data('prot/dayhoff.zip') + + c.run_sourmash('search', sigfile1, db_out, '--threshold', '0.0') + assert '2 matches:' in c.last_result.out + + c.run_sourmash('gather', sigfile1, db_out, '--threshold', '0.0') + assert 'found 1 matches total' in c.last_result.out + assert 'the recovered matches hit 100.0% of the query' in c.last_result.out + + +@utils.in_thisdir +def test_zip_protein_command_search_combined(c): + # test command-line search/gather of combined zipfile with protein sigs + sigfile1 = utils.get_test_data('prot/protein/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') + db_out = utils.get_test_data('prot/all.zip') + + c.run_sourmash('search', sigfile1, db_out, '--threshold', '0.0') + assert '2 matches:' in c.last_result.out + + c.run_sourmash('gather', sigfile1, db_out) + assert 'found 1 matches total' in c.last_result.out + assert 'the recovered matches hit 100.0% of the query' in c.last_result.out + + +@utils.in_thisdir +def test_zip_hp_command_search_combined(c): + # test command-line search/gather of combined zipfile with hp sigs + sigfile1 = utils.get_test_data('prot/hp/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') + db_out = utils.get_test_data('prot/all.zip') + + c.run_sourmash('search', sigfile1, db_out, '--threshold', '0.0') + assert '2 matches:' in c.last_result.out + + c.run_sourmash('gather', sigfile1, db_out, '--threshold', '0.0') + assert 'found 1 matches total' in c.last_result.out + assert 'the recovered matches hit 100.0% of the query' in c.last_result.out + + +@utils.in_thisdir +def test_zip_dayhoff_command_search_combined(c): + # test command-line search/gather of combined zipfile with dayhoff sigs + sigfile1 = utils.get_test_data('prot/dayhoff/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') + db_out = utils.get_test_data('prot/all.zip') + + c.run_sourmash('search', sigfile1, db_out, '--threshold', '0.0') + assert '2 matches:' in c.last_result.out + + c.run_sourmash('gather', sigfile1, db_out, '--threshold', '0.0') + assert 'found 1 matches total' in c.last_result.out + assert 'the recovered matches hit 100.0% of the query' in c.last_result.out diff --git a/tests/test_sbt.py b/tests/test_sbt.py index 25d864ea83..50b4d73b2c 100644 --- a/tests/test_sbt.py +++ b/tests/test_sbt.py @@ -798,8 +798,7 @@ def test_sbt_protein_command_index(c): @utils.in_thisdir def test_sbt_protein_command_search(c): - # test command-line search/gather of LCA database with protein sigs - # (LCA database created as above) + # test command-line search/gather of SBT database with protein sigs sigfile1 = utils.get_test_data('prot/protein/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') db_out = utils.get_test_data('prot/protein.sbt.zip') @@ -844,8 +843,7 @@ def test_sbt_hp_command_index(c): @utils.in_thisdir def test_sbt_hp_command_search(c): - # test command-line search/gather of LCA database with hp sigs - # (LCA database created as above) + # test command-line search/gather of SBT database with hp sigs sigfile1 = utils.get_test_data('prot/hp/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') db_out = utils.get_test_data('prot/hp.sbt.zip') @@ -890,8 +888,7 @@ def test_sbt_dayhoff_command_index(c): @utils.in_thisdir def test_sbt_dayhoff_command_search(c): - # test command-line search/gather of LCA database with dayhoff sigs - # (LCA database created as above) + # test command-line search/gather of SBT database with dayhoff sigs sigfile1 = utils.get_test_data('prot/dayhoff/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') db_out = utils.get_test_data('prot/dayhoff.sbt.zip') From 8c9c9ae1ad2cd720d104844db950c6ea41e195c4 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Feb 2021 05:56:19 -0800 Subject: [PATCH 04/71] add sig describe test for loading from zipfile --- tests/test_cmd_signature.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_cmd_signature.py b/tests/test_cmd_signature.py index 4152ceab33..fb0eb108b2 100644 --- a/tests/test_cmd_signature.py +++ b/tests/test_cmd_signature.py @@ -1421,6 +1421,27 @@ def test_sig_describe_1_dir(c): assert line.strip() in out +@utils.in_tempdir +def test_sig_describe_1_zipfile(c): + # get basic info on multiple signatures in a zipfile + sigs = utils.get_test_data('prot/all.zip') + c.run_sourmash('sig', 'describe', sigs) + + out = c.last_result.out + print(c.last_result) + + expected_output = """\ +k=19 molecule=dayhoff num=0 scaled=100 seed=42 track_abundance=0 +k=19 molecule=dayhoff num=0 scaled=100 seed=42 track_abundance=0 +k=19 molecule=hp num=0 scaled=100 seed=42 track_abundance=0 +k=19 molecule=hp num=0 scaled=100 seed=42 track_abundance=0 +k=19 molecule=protein num=0 scaled=100 seed=42 track_abundance=0 +k=19 molecule=protein num=0 scaled=100 seed=42 track_abundance=0 +""".splitlines() + for line in expected_output: + assert line.strip() in out + + @utils.in_thisdir def test_sig_describe_stdin(c): sig = utils.get_test_data('prot/protein/GCA_001593925.1_ASM159392v1_protein.faa.gz.sig') From 7087d8234f80749866b6cfdf421aa61efe5c8835 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Feb 2021 06:05:55 -0800 Subject: [PATCH 05/71] fix load_file_as_index to support zipfiles --- src/sourmash/sourmash_args.py | 16 ++++++++-------- tests/test_api.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index f249c7db8c..a7cb099327 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -253,7 +253,7 @@ def check_lca_db_is_compatible(filename, db, query): def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None): """ - Load one or more SBTs, LCAs, and/or signatures. + Load one or more SBTs, LCAs, and/or collections of signatures. Check for compatibility with query. """ @@ -368,7 +368,7 @@ class DatabaseType(Enum): def _load_database(filename, traverse_yield_all, *, cache_size=None): - """Load file as a database - list of signatures, LCA, SBT, etc. + """Load file as a database - list of signatures, LCA, SBT, Zip file, etc. Return (db, dbtype), where dbtype is a DatabaseType enum. @@ -491,8 +491,8 @@ def _select_sigs(siglist, ksize, moltype): def load_file_as_index(filename, yield_all_files=False): """Load 'filename' as a database; generic database loader. - If 'filename' contains an SBT or LCA indexed database, will return - the appropriate objects. + If 'filename' contains an SBT or LCA indexed database, or a regular + Zip file, will return the appropriate objects. If 'filename' is a JSON file containing one or more signatures, will return an Index object containing those signatures. @@ -502,14 +502,14 @@ def load_file_as_index(filename, yield_all_files=False): attempt to load all files. """ db, dbtype = _load_database(filename, yield_all_files) - if dbtype in (DatabaseType.LCA, DatabaseType.SBT): + if dbtype in (DatabaseType.LCA, DatabaseType.SBT, DatabaseType.ZIPFILE): return db # already an index! elif dbtype == DatabaseType.SIGLIST: # turn siglist into a LinearIndex idx = LinearIndex(db, filename) return idx else: - assert 0 # unknown enum!? + raise Exception # unknown enum!? def load_file_as_signatures(filename, select_moltype=None, ksize=None, @@ -517,8 +517,8 @@ def load_file_as_signatures(filename, select_moltype=None, ksize=None, progress=None): """Load 'filename' as a collection of signatures. Return an iterable. - If 'filename' contains an SBT or LCA indexed database, will return - a signatures() generator. + If 'filename' contains an SBT or LCA indexed database, or a regular + Zip file, will return a signatures() generator. If 'filename' is a JSON file containing one or more signatures, will return a list of those signatures. diff --git a/tests/test_api.py b/tests/test_api.py index a6c298d3c3..7d6dbf381c 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -49,6 +49,22 @@ def test_load_index_3(): assert len(sigs) == 2 +def test_load_index_4(): + testfile = utils.get_test_data('prot/all.zip') + idx = sourmash.load_file_as_index(testfile) + + sigs = list(idx.signatures()) + assert len(sigs) == 6 + + +def test_load_index_4_b(): + testfile = utils.get_test_data('prot/protein.zip') + idx = sourmash.load_file_as_index(testfile) + + sigs = list(idx.signatures()) + assert len(sigs) == 2 + + def test_load_fasta_as_signature(): # try loading a fasta file - should fail with informative exception testfile = utils.get_test_data('short.fa') From c75bd83ea411ae27a6e16cf919d5bd2048df31b9 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Feb 2021 06:22:40 -0800 Subject: [PATCH 06/71] rename force; add docstrings --- src/sourmash/index.py | 24 ++++++++++++++++++------ src/sourmash/sourmash_args.py | 12 +++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 912e91413b..1f90b8c520 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -123,6 +123,9 @@ def select(self, ksize=None, moltype=None): "" class LinearIndex(Index): + """\ + An in-memory collection of signatures. + """ def __init__(self, _signatures=None, filename=None): self._signatures = [] if _signatures: @@ -163,12 +166,17 @@ def select_sigs(siglist, ksize, moltype): class ZipFileLinearIndex(Index): + """\ + A read-only collection of signatures in a zip file. + + Does not support `insert` or `save`. + """ def __init__(self, zf, select_ksize=None, select_moltype=None, - force=False): + traverse_yield_all=False): self.zf = zf self.ksize = select_ksize self.moltype = select_moltype - self.force = force + self.traverse_yield_all = traverse_yield_all @property def filename(self): @@ -181,15 +189,17 @@ def save(self, path): raise NotImplementedError @classmethod - def load(cls, location, force=False): + def load(cls, location, traverse_yield_all=False): + "Class method to load a zipfile." zf = zipfile.ZipFile(location, 'r') - return cls(zf, force=force) + return cls(zf, traverse_yield_all=traverse_yield_all) def signatures(self): + "Load all signatures in the zip file." from .signature import load_signatures for zipinfo in self.zf.infolist(): # should we load this file? if it ends in .sig OR we are forcing: - if zipinfo.filename.endswith('.sig') or self.force: + if zipinfo.filename.endswith('.sig') or self.traverse_yield_all: fp = self.zf.open(zipinfo) # now load all the signatures and select on ksize/moltype: @@ -199,4 +209,6 @@ def signatures(self): yield ss def select(self, ksize=None, moltype=None): - return ZipFileLinearIndex(self.zf, ksize, moltype, self.force) + "Select signatures in zip file based on ksize/moltype." + return ZipFileLinearIndex(self.zf, ksize, moltype, + self.traverse_yield_all) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index a7cb099327..99988b0611 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -451,10 +451,12 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): if not loaded: # try load as ZipFileLinearIndex if filename.endswith('.zip'): try: - db = ZipFileLinearIndex.load(filename) + db = ZipFileLinearIndex.load(filename, + traverse_yield_all=traverse_yield_all) loaded = True dbtype = DatabaseType.ZIPFILE except: + raise pass # check to see if it's a FASTA/FASTQ record (i.e. screed loadable) @@ -492,7 +494,9 @@ def load_file_as_index(filename, yield_all_files=False): """Load 'filename' as a database; generic database loader. If 'filename' contains an SBT or LCA indexed database, or a regular - Zip file, will return the appropriate objects. + Zip file, will return the appropriate objects. If a Zip file and + yield_all_files=True, will try to load all files within zip, not just + .sig files. If 'filename' is a JSON file containing one or more signatures, will return an Index object containing those signatures. @@ -518,7 +522,9 @@ def load_file_as_signatures(filename, select_moltype=None, ksize=None, """Load 'filename' as a collection of signatures. Return an iterable. If 'filename' contains an SBT or LCA indexed database, or a regular - Zip file, will return a signatures() generator. + Zip file, will return a signatures() generator. If a Zip file and + yield_all_files=True, will try to load all files within zip, not just + .sig files. If 'filename' is a JSON file containing one or more signatures, will return a list of those signatures. From 92e5fdc62272de4183427d919d9ed1663f76da48 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 6 Mar 2021 15:50:50 -0800 Subject: [PATCH 07/71] add an IndexOfIndexes class --- src/sourmash/index.py | 56 +++++++++++++++++++++++++++++ tests/test_index.py | 84 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 8dd4069f04..5945f0c662 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -159,3 +159,59 @@ def select_sigs(siglist, ksize, moltype): siglist=select_sigs(self._signatures, ksize, moltype) return LinearIndex(siglist, self.filename) + + +class IndexOfIndexes(Index): + def __init__(self, index_list, source_list): + self.index_list = list(index_list) + self.source_list = list(source_list) + assert len(index_list) == len(source_list) + + def signatures(self): + for idx in self.index_list: + for ss in idx.signatures(): + yield ss + + def insert(self, *args): + raise NotImplementedError + + @classmethod + def load(self, *args): + raise NotImplementedError + + def save(self, *args): + raise NotImplementedError + + def select(self, ksize=None, moltype=None): + new_idx_list = [] + new_src_list = [] + for idx, src in zip(self.index_list, self.source_list): + idx = idx.select(ksize=ksize, moltype=moltype) + new_idx_list.append(idx) + new_src_list.append(src) + + return IndexOfIndexes(new_idx_list, new_src_list) + + + def search(self, query, *args, **kwargs): + # do the actual search: + matches = [] + for idx, src in zip(self.index_list, self.source_list): + for (score, ss, filename) in idx.search(query, *args, **kwargs): + matches.append((score, ss, src)) + + # sort! + matches.sort(key=lambda x: -x[0]) + return matches + + def gather(self, query, *args, **kwargs): + "Return the match with the best Jaccard containment in the Index." + # actually do search! + results = [] + for idx, src in zip(self.index_list, self.source_list): + for (score, ss, filename) in idx.gather(query, *args, **kwargs): + results.append((score, ss, src)) + + results.sort(reverse=True, key=lambda x: (x[0], x[1].md5sum())) + + return results diff --git a/tests/test_index.py b/tests/test_index.py index 1313162a2e..ceea3559e5 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -4,7 +4,7 @@ import sourmash from sourmash import load_one_signature, SourmashSignature -from sourmash.index import LinearIndex +from sourmash.index import LinearIndex, IndexOfIndexes from sourmash.sbt import SBT, GraphFactory, Leaf import sourmash_tst_utils as utils @@ -393,3 +393,85 @@ def test_index_same_md5sum_zipstorage(c): # should have 3 files, 1 internal and two sigs. We check for 4 because the # directory also shows in namelist() assert len([f for f in zout.namelist() if f.startswith(".sbt.zzz/")]) == 4 + + +def test_indexindex_search(): + sig2 = utils.get_test_data('2.fa.sig') + sig47 = utils.get_test_data('47.fa.sig') + sig63 = utils.get_test_data('63.fa.sig') + + ss2 = sourmash.load_one_signature(sig2, ksize=31) + ss47 = sourmash.load_one_signature(sig47) + ss63 = sourmash.load_one_signature(sig63) + + lidx1 = LinearIndex() + lidx1.insert(ss2) + lidx2 = LinearIndex() + lidx2.insert(ss47) + lidx3 = LinearIndex() + lidx3.insert(ss63) + + lidx = IndexOfIndexes([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) + + # now, search for sig2 + sr = lidx.search(ss2, threshold=1.0) + print([s[1].name for s in sr]) + assert len(sr) == 1 + assert sr[0][1] == ss2 + + # search for sig47 with lower threshold; search order not guaranteed. + sr = lidx.search(ss47, threshold=0.1) + print([s[1].name for s in sr]) + assert len(sr) == 2 + sr.sort(key=lambda x: -x[0]) + assert sr[0][1] == ss47 + assert sr[1][1] == ss63 + + # search for sig63 with lower threshold; search order not guaranteed. + sr = lidx.search(ss63, threshold=0.1) + print([s[1].name for s in sr]) + assert len(sr) == 2 + sr.sort(key=lambda x: -x[0]) + assert sr[0][1] == ss63 + assert sr[1][1] == ss47 + + # search for sig63 with high threshold => 1 match + sr = lidx.search(ss63, threshold=0.8) + print([s[1].name for s in sr]) + assert len(sr) == 1 + sr.sort(key=lambda x: -x[0]) + assert sr[0][1] == ss63 + + +def test_indexindex_gather(): + sig2 = utils.get_test_data('2.fa.sig') + sig47 = utils.get_test_data('47.fa.sig') + sig63 = utils.get_test_data('63.fa.sig') + + ss2 = sourmash.load_one_signature(sig2, ksize=31) + ss47 = sourmash.load_one_signature(sig47) + ss63 = sourmash.load_one_signature(sig63) + + + lidx1 = LinearIndex() + lidx1.insert(ss2) + lidx2 = LinearIndex() + lidx2.insert(ss47) + lidx3 = LinearIndex() + lidx3.insert(ss63) + + lidx = IndexOfIndexes([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) + + matches = lidx.gather(ss2) + assert len(matches) == 1 + assert matches[0][0] == 1.0 + assert matches[0][1] == ss2 + + matches = lidx.gather(ss47) + assert len(matches) == 2 + assert matches[0][0] == 1.0 + assert matches[0][1] == ss47 + assert round(matches[1][0], 2) == 0.49 + assert matches[1][1] == ss63 + + From 5c71e11d47f78f43bf9953351d0c32d84b7b9a07 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 6 Mar 2021 16:41:59 -0800 Subject: [PATCH 08/71] rename to MultiIndex --- src/sourmash/index.py | 3 ++- tests/test_index.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 5945f0c662..ed6b2be399 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -161,7 +161,8 @@ def select_sigs(siglist, ksize, moltype): return LinearIndex(siglist, self.filename) -class IndexOfIndexes(Index): +class MultiIndex(Index): + "An Index class that wraps other Index classes." def __init__(self, index_list, source_list): self.index_list = list(index_list) self.source_list = list(source_list) diff --git a/tests/test_index.py b/tests/test_index.py index ceea3559e5..11b46b6e6c 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -4,7 +4,7 @@ import sourmash from sourmash import load_one_signature, SourmashSignature -from sourmash.index import LinearIndex, IndexOfIndexes +from sourmash.index import LinearIndex, MultiIndex from sourmash.sbt import SBT, GraphFactory, Leaf import sourmash_tst_utils as utils @@ -411,7 +411,7 @@ def test_indexindex_search(): lidx3 = LinearIndex() lidx3.insert(ss63) - lidx = IndexOfIndexes([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) + lidx = MultiIndex([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) # now, search for sig2 sr = lidx.search(ss2, threshold=1.0) @@ -460,7 +460,7 @@ def test_indexindex_gather(): lidx3 = LinearIndex() lidx3.insert(ss63) - lidx = IndexOfIndexes([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) + lidx = MultiIndex([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) matches = lidx.gather(ss2) assert len(matches) == 1 From 85efdaf70eea915c3c47538be01a44ff22cacf75 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 6 Mar 2021 20:22:30 -0800 Subject: [PATCH 09/71] switch to using MultiIndex for loading from a directory --- src/sourmash/index.py | 3 +-- src/sourmash/sourmash_args.py | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index ed6b2be399..d755b743d4 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -191,8 +191,7 @@ def select(self, ksize=None, moltype=None): new_idx_list.append(idx) new_src_list.append(src) - return IndexOfIndexes(new_idx_list, new_src_list) - + return MultiIndex(new_idx_list, new_src_list) def search(self, query, *args, **kwargs): # do the actual search: diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 258b99cee0..64a2825773 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -16,7 +16,7 @@ from . import signature from .logging import notify, error -from .index import LinearIndex +from .index import LinearIndex, MultiIndex from . import signature as sig from .sbt import SBT from .sbtmh import SigLeaf @@ -278,12 +278,10 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) if os.path.isdir(filename): assert dbtype == DatabaseType.SIGLIST - siglist = _select_sigs(db, moltype=query_moltype, ksize=query_ksize) - siglist = filter_compatible_signatures(query, siglist, 1) - linear = LinearIndex(siglist, filename=filename) - databases.append((linear, filename, False)) + db = db.select(moltype=query_moltype, ksize=query_ksize) + databases.append((db, filename, False)) - n_signatures += len(linear) + n_signatures += 1 # @CTB # SBT elif dbtype == DatabaseType.SBT: @@ -372,22 +370,23 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): # load signatures from directory if not loaded and os.path.isdir(filename): - all_sigs = [] + index_list = [] + source_list = [] for thisfile in traverse_find_sigs([filename], traverse_yield_all): try: - with open(thisfile, 'rt') as fp: - x = signature.load_signatures(fp, do_raise=True) - siglist = list(x) - all_sigs.extend(siglist) + idx = LinearIndex.load(thisfile) + index_list.append(idx) + source_list.append(thisfile) except (IOError, sourmash.exceptions.SourmashError): if traverse_yield_all: continue else: raise - loaded=True - db = all_sigs - dbtype = DatabaseType.SIGLIST + if index_list: + loaded=True + db = MultiIndex(index_list, source_list) + dbtype = DatabaseType.SIGLIST # load signatures from single file try: From 04f9de17d67191cb45e08971aca63936761d87a7 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 7 Mar 2021 06:46:29 -0800 Subject: [PATCH 10/71] some more MultiIndex tests --- src/sourmash/index.py | 7 +++++-- tests/test_index.py | 41 +++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index d755b743d4..a8503fe455 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -122,6 +122,7 @@ def select(self, ksize=None, moltype=None): "" class LinearIndex(Index): + "An Index for a collection of signatures. Can load from a .sig file." def __init__(self, _signatures=None, filename=None): self._signatures = [] if _signatures: @@ -198,7 +199,8 @@ def search(self, query, *args, **kwargs): matches = [] for idx, src in zip(self.index_list, self.source_list): for (score, ss, filename) in idx.search(query, *args, **kwargs): - matches.append((score, ss, src)) + best_src = src or filename # override if src provided + matches.append((score, ss, best_src)) # sort! matches.sort(key=lambda x: -x[0]) @@ -210,7 +212,8 @@ def gather(self, query, *args, **kwargs): results = [] for idx, src in zip(self.index_list, self.source_list): for (score, ss, filename) in idx.gather(query, *args, **kwargs): - results.append((score, ss, src)) + best_src = src or filename # override if src provided + results.append((score, ss, best_src)) results.sort(reverse=True, key=lambda x: (x[0], x[1].md5sum())) diff --git a/tests/test_index.py b/tests/test_index.py index 11b46b6e6c..05e1a49750 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -395,7 +395,7 @@ def test_index_same_md5sum_zipstorage(c): assert len([f for f in zout.namelist() if f.startswith(".sbt.zzz/")]) == 4 -def test_indexindex_search(): +def test_multi_index_search(): sig2 = utils.get_test_data('2.fa.sig') sig47 = utils.get_test_data('47.fa.sig') sig63 = utils.get_test_data('63.fa.sig') @@ -404,20 +404,20 @@ def test_indexindex_search(): ss47 = sourmash.load_one_signature(sig47) ss63 = sourmash.load_one_signature(sig63) - lidx1 = LinearIndex() - lidx1.insert(ss2) - lidx2 = LinearIndex() - lidx2.insert(ss47) - lidx3 = LinearIndex() - lidx3.insert(ss63) + lidx1 = LinearIndex.load(sig2) + lidx2 = LinearIndex.load(sig47) + lidx3 = LinearIndex.load(sig63) - lidx = MultiIndex([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) + # create MultiIindex with source location override + lidx = MultiIndex([lidx1, lidx2, lidx3], ['A', None, 'C']) + lidx = lidx.select(ksize=31) # now, search for sig2 sr = lidx.search(ss2, threshold=1.0) print([s[1].name for s in sr]) assert len(sr) == 1 assert sr[0][1] == ss2 + assert sr[0][2] == 'A' # source override # search for sig47 with lower threshold; search order not guaranteed. sr = lidx.search(ss47, threshold=0.1) @@ -425,7 +425,9 @@ def test_indexindex_search(): assert len(sr) == 2 sr.sort(key=lambda x: -x[0]) assert sr[0][1] == ss47 + assert sr[0][2] == sig47 # source was set to None, so no override assert sr[1][1] == ss63 + assert sr[1][2] == 'C' # source override # search for sig63 with lower threshold; search order not guaranteed. sr = lidx.search(ss63, threshold=0.1) @@ -433,7 +435,9 @@ def test_indexindex_search(): assert len(sr) == 2 sr.sort(key=lambda x: -x[0]) assert sr[0][1] == ss63 + assert sr[0][2] == 'C' # source override assert sr[1][1] == ss47 + assert sr[1][2] == sig47 # source was set to None, so no override # search for sig63 with high threshold => 1 match sr = lidx.search(ss63, threshold=0.8) @@ -441,9 +445,10 @@ def test_indexindex_search(): assert len(sr) == 1 sr.sort(key=lambda x: -x[0]) assert sr[0][1] == ss63 + assert sr[0][2] == 'C' # source override -def test_indexindex_gather(): +def test_multi_index_gather(): sig2 = utils.get_test_data('2.fa.sig') sig47 = utils.get_test_data('47.fa.sig') sig63 = utils.get_test_data('63.fa.sig') @@ -452,26 +457,26 @@ def test_indexindex_gather(): ss47 = sourmash.load_one_signature(sig47) ss63 = sourmash.load_one_signature(sig63) + lidx1 = LinearIndex.load(sig2) + lidx2 = LinearIndex.load(sig47) + lidx3 = LinearIndex.load(sig63) - lidx1 = LinearIndex() - lidx1.insert(ss2) - lidx2 = LinearIndex() - lidx2.insert(ss47) - lidx3 = LinearIndex() - lidx3.insert(ss63) - - lidx = MultiIndex([lidx1, lidx2, lidx3], [sig2, sig47, sig63]) + # create MultiIindex with source location override + lidx = MultiIndex([lidx1, lidx2, lidx3], ['A', None, 'C']) + lidx = lidx.select(ksize=31) matches = lidx.gather(ss2) assert len(matches) == 1 assert matches[0][0] == 1.0 - assert matches[0][1] == ss2 + assert matches[0][2] == 'A' matches = lidx.gather(ss47) assert len(matches) == 2 assert matches[0][0] == 1.0 assert matches[0][1] == ss47 + assert matches[0][2] == sig47 # no source override assert round(matches[1][0], 2) == 0.49 assert matches[1][1] == ss63 + assert matches[1][2] == 'C' # source override From 201a89a0f29c61191a069ba3f6b01ce670e1dcde Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 7 Mar 2021 06:55:18 -0800 Subject: [PATCH 11/71] add test of MultiIndex.signatures --- tests/test_index.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_index.py b/tests/test_index.py index 05e1a49750..1b9ae93402 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -480,3 +480,25 @@ def test_multi_index_gather(): assert matches[1][2] == 'C' # source override +def test_multi_index_signatures(): + sig2 = utils.get_test_data('2.fa.sig') + sig47 = utils.get_test_data('47.fa.sig') + sig63 = utils.get_test_data('63.fa.sig') + + ss2 = sourmash.load_one_signature(sig2, ksize=31) + ss47 = sourmash.load_one_signature(sig47) + ss63 = sourmash.load_one_signature(sig63) + + lidx1 = LinearIndex.load(sig2) + lidx2 = LinearIndex.load(sig47) + lidx3 = LinearIndex.load(sig63) + + # create MultiIindex with source location override + lidx = MultiIndex([lidx1, lidx2, lidx3], ['A', None, 'C']) + lidx = lidx.select(ksize=31) + + siglist = list(lidx.signatures()) + assert len(siglist) == 3 + assert ss2 in siglist + assert ss47 in siglist + assert ss63 in siglist From 07d2c321bd7cf219377d01db28a44a24c6364aa0 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 7 Mar 2021 06:55:35 -0800 Subject: [PATCH 12/71] add docstring for MultiIndex --- src/sourmash/index.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index a8503fe455..4160730da4 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -163,7 +163,16 @@ def select_sigs(siglist, ksize, moltype): class MultiIndex(Index): - "An Index class that wraps other Index classes." + """An Index class that wraps other Index classes. + + The MultiIndex constructor takes two arguments: a list of Index + objects, and a matching list of sources (filenames, etc.) If the + source is not None, then it will be used to override the 'filename' + in the triple that is returned by search and gather. + + One specific use for this is when loading signatures from a directory; + MultiIndex will properly record which files provided which signatures. + """ def __init__(self, index_list, source_list): self.index_list = list(index_list) self.source_list = list(source_list) From 61d15c324f09975f81c58e8abbe7f5f663cf3ef5 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 7 Mar 2021 07:13:57 -0800 Subject: [PATCH 13/71] stop special-casing SIGLISTs --- src/sourmash/sourmash_args.py | 57 ++++++++++++++++------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 64a2825773..a818cc1ea9 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -306,7 +306,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) # signature file elif dbtype == DatabaseType.SIGLIST: - siglist = _select_sigs(db, moltype=query_moltype, ksize=query_ksize) + db = db.select(moltype=query_moltype, ksize=query_ksize) + siglist = db.signatures() siglist = filter_compatible_signatures(query, siglist, False) siglist = list(siglist) if not siglist: @@ -388,32 +389,33 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): db = MultiIndex(index_list, source_list) dbtype = DatabaseType.SIGLIST - # load signatures from single file - try: - # CTB: could make this a generator, with some trickery; but for - # now, just force into list. - with open(filename, 'rt') as fp: - db = signature.load_signatures(fp, do_raise=True) - db = list(db) - - loaded = True - dbtype = DatabaseType.SIGLIST - except Exception as exc: - pass + # load signatures from single signature file + if not loaded: + try: + with open(filename, 'rt') as fp: + db = LinearIndex.load(fp) + dbtype = DatabaseType.SIGLIST + loaded = True + except Exception as exc: + pass # try load signatures from single file (list of signature paths) if not loaded: try: - db = [] - with open(filename, 'rt') as fp: - for line in fp: - line = line.strip() - if line: - sigs = load_file_as_signatures(line) - db += list(sigs) + idx_list = [] + src_list = [] - loaded = True + file_list = load_file_list_of_signatures(filename) + for fname in file_list: + idx = load_file_as_index(fname) + src = fname + + idx_list.append(idx) + src_list.append(src) + + db = MultiIndex(idx_list, src_list) dbtype = DatabaseType.SIGLIST + loaded = True except Exception as exc: pass @@ -451,7 +453,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): raise OSError("Error while reading signatures from '{}' - got sequences instead! Is this a FASTA/FASTQ file?".format(filename)) if not loaded: - raise OSError("Error while reading signatures from '{}'.".format(filename)) + raise OSError(f"Error while reading signatures from '{filename}'.") return db, dbtype @@ -509,15 +511,8 @@ def load_file_as_signatures(filename, select_moltype=None, ksize=None, progress.notify(filename) db, dbtype = _load_database(filename, yield_all_files) - - loader = None - if dbtype in (DatabaseType.LCA, DatabaseType.SBT): - db = db.select(moltype=select_moltype, ksize=ksize) - loader = db.signatures() - elif dbtype == DatabaseType.SIGLIST: - loader = _select_sigs(db, moltype=select_moltype, ksize=ksize) - else: - assert 0 # unknown enum!? + db = db.select(moltype=select_moltype, ksize=ksize) + loader = db.signatures() if progress: return progress.start_file(filename, loader) From 16f9ee2c1d73e822f219d696e661626dd838c897 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 7 Mar 2021 07:15:58 -0800 Subject: [PATCH 14/71] fix test to match more informative error message --- tests/test_sourmash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index 2f144e32ed..47e05d57fd 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -3447,7 +3447,7 @@ def test_gather_error_no_sigs_traverse(c): err = c.last_result.err print(err) - assert '** ERROR: no signatures or databases loaded?' in err + assert f"Error while reading signatures from '{emptydir}'" in err assert not 'found 0 matches total;' in err From c6bf3148b1627b72aaff834bcca41bf0d62d0b63 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 7 Mar 2021 07:22:43 -0800 Subject: [PATCH 15/71] switch to using LinearIndex.load for stdin, too --- src/sourmash/sourmash_args.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index a818cc1ea9..43b4c77805 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -364,10 +364,9 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): # special case stdin if not loaded and filename == '-': - db = signature.load_signatures(sys.stdin, do_raise=True) - db = list(db) - loaded = True + db = LinearIndex.load(sys.stdin) dbtype = DatabaseType.SIGLIST + loaded = True # load signatures from directory if not loaded and os.path.isdir(filename): @@ -480,14 +479,7 @@ def load_file_as_index(filename, yield_all_files=False): attempt to load all files. """ db, dbtype = _load_database(filename, yield_all_files) - if dbtype in (DatabaseType.LCA, DatabaseType.SBT): - return db # already an index! - elif dbtype == DatabaseType.SIGLIST: - # turn siglist into a LinearIndex - idx = LinearIndex(db, filename) - return idx - else: - assert 0 # unknown enum!? + return db def load_file_as_signatures(filename, select_moltype=None, ksize=None, From dd0f3b8d264d71e7c559b3a8af815f4834d9cb99 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 8 Mar 2021 06:38:23 -0800 Subject: [PATCH 16/71] add __len__ to MultiIndex --- src/sourmash/index.py | 3 +++ src/sourmash/sourmash_args.py | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 4160730da4..a8cc322d55 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -183,6 +183,9 @@ def signatures(self): for ss in idx.signatures(): yield ss + def __len__(self): + return sum([ len(idx) for idx in self.index_list ]) + def insert(self, *args): raise NotImplementedError diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 43b4c77805..37a52aa6b4 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -273,15 +273,17 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) sys.exit(-1) # are we collecting signatures from a directory/path? - # NOTE: error messages about loading will now be attributed to - # directory, not individual file. if os.path.isdir(filename): + # CTB: combine with SIGLIST below? assert dbtype == DatabaseType.SIGLIST db = db.select(moltype=query_moltype, ksize=query_ksize) + if not db: + notify("no compatible signatures found in '{}'", filename) + sys.exit(-1) databases.append((db, filename, False)) - n_signatures += 1 # @CTB + n_signatures += len(db) # SBT elif dbtype == DatabaseType.SBT: @@ -297,7 +299,6 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) elif dbtype == DatabaseType.LCA: if not check_lca_db_is_compatible(filename, db, query): sys.exit(-1) - query_scaled = query.minhash.scaled notify('loaded LCA {}', filename, end='\r') n_databases += 1 From 9211a74e7731fd0aa4bb2511c3465a10af125b7e Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 8 Mar 2021 06:53:33 -0800 Subject: [PATCH 17/71] add check_csv to check for appropriate filename loading info --- tests/test_sourmash.py | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index 47e05d57fd..cd3b669176 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -1570,6 +1570,33 @@ def test_search_metagenome_traverse(): assert '13 matches; showing first 3:' in out +def test_search_metagenome_traverse_check_csv(): + with utils.TempDirectory() as location: + testdata_dir = utils.get_test_data('gather') + + query_sig = utils.get_test_data('gather/combined.sig') + out_csv = os.path.join(location, 'out.csv') + + cmd = f'search {query_sig} {testdata_dir} -k 21 -o {out_csv}' + status, out, err = utils.runscript('sourmash', cmd.split(' '), + in_directory=location) + + print(out) + print(err) + + with open(out_csv, 'rt') as fp: + prefix_len = len(testdata_dir) + r = csv.DictReader(fp) + for row in r: + filename = row['filename'] + assert filename.startswith(testdata_dir) + # should have full path to file sig was loaded from + assert len(filename) > prefix_len + + assert ' 33.2% NC_003198.1 Salmonella enterica subsp. enterica serovar T...' in out + assert '13 matches; showing first 3:' in out + + # explanation: you cannot downsample a scaled SBT to match a scaled # signature, so make sure that when you try such a search, it fails! # (you *can* downsample a signature to match an SBT.) @@ -3246,6 +3273,46 @@ def test_gather_metagenome_traverse(): 'NC_011294.1 Salmonella enterica subsp...' in out)) +def test_gather_metagenome_traverse_check_csv(): + with utils.TempDirectory() as location: + # set up a directory $location/gather that contains + # everything in the 'tests/test-data/gather' directory + # *except* the query sequence, which is 'combined.sig'. + testdata_dir = utils.get_test_data('gather') + copy_testdata = os.path.join(location, 'somesigs') + shutil.copytree(testdata_dir, copy_testdata) + os.unlink(os.path.join(copy_testdata, 'combined.sig')) + + query_sig = utils.get_test_data('gather/combined.sig') + out_csv = os.path.join(location, 'out.csv') + + # now, feed in the new directory -- + cmd = f'gather {query_sig} {copy_testdata} -k 21 --threshold-bp=0' + cmd += f' -o {out_csv}' + status, out, err = utils.runscript('sourmash', cmd.split(' '), + in_directory=location) + + print(cmd) + print(out) + print(err) + + with open(out_csv, 'rt') as fp: + prefix_len = len(copy_testdata) + r = csv.DictReader(fp) + for row in r: + filename = row['filename'] + assert filename.startswith(copy_testdata) + # should have full path to file sig was loaded from + assert len(filename) > prefix_len + + assert 'found 12 matches total' in out + assert 'the recovered matches hit 100.0% of the query' in out + assert all(('4.9 Mbp 33.2% 100.0%' in out, + 'NC_003198.1 Salmonella enterica subsp...' in out)) + assert all(('4.7 Mbp 0.5% 1.5%' in out, + 'NC_011294.1 Salmonella enterica subsp...' in out)) + + def test_gather_metagenome_output_unassigned(): with utils.TempDirectory() as location: testdata_glob = utils.get_test_data('gather/GCF_000195995*g') From 75069ff0ae43107b18f780a8298661c1b8b08bb4 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 8 Mar 2021 06:56:43 -0800 Subject: [PATCH 18/71] add comment --- tests/test_sourmash.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index cd3b669176..71b5ebec66 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -1571,6 +1571,9 @@ def test_search_metagenome_traverse(): def test_search_metagenome_traverse_check_csv(): + # this test confirms that the CSV 'filename' output for signatures loaded + # via directory traversal properly contains the actual path to the + # signature file from which the signature was loaded. with utils.TempDirectory() as location: testdata_dir = utils.get_test_data('gather') @@ -3274,6 +3277,9 @@ def test_gather_metagenome_traverse(): def test_gather_metagenome_traverse_check_csv(): + # this test confirms that the CSV 'filename' output for signatures loaded + # via directory traversal properly contains the actual path to the + # signature file from which the signature was loaded. with utils.TempDirectory() as location: # set up a directory $location/gather that contains # everything in the 'tests/test-data/gather' directory From 9f39623f04e928a6af2f1cf8d182d94d5e773976 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 8 Mar 2021 17:24:21 -0800 Subject: [PATCH 19/71] fix databases load --- src/sourmash/sourmash_args.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 906431cc67..b36cf3bbbd 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -283,7 +283,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) if not db: notify("no compatible signatures found in '{}'", filename) sys.exit(-1) - databases.append((db, filename, False)) + databases.append(db) n_signatures += len(db) # SBT From ac63cf8fe7d3070c25691bce02a9e393da34bc40 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 8 Mar 2021 17:26:38 -0800 Subject: [PATCH 20/71] more tests needed --- src/sourmash/sourmash_args.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index b36cf3bbbd..0b826f92fe 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -280,6 +280,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) assert dbtype == DatabaseType.SIGLIST db = db.select(moltype=query_moltype, ksize=query_ksize) + # @CTB filter compatible signatures here, too. write test. if not db: notify("no compatible signatures found in '{}'", filename) sys.exit(-1) From 5590d70ddf226cbcca691c5c308ef42ce431da69 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Tue, 9 Mar 2021 06:41:49 -0800 Subject: [PATCH 21/71] add tests for incompatible signatures --- src/sourmash/sourmash_args.py | 11 ++++++-- tests/test_sourmash.py | 52 +++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 0b826f92fe..f0a8e5b3c5 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -311,8 +311,15 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) elif dbtype == DatabaseType.SIGLIST: db = db.select(moltype=query_moltype, ksize=query_ksize) siglist = db.signatures() - siglist = filter_compatible_signatures(query, siglist, False) - siglist = list(siglist) + try: + # CTB: it's not clear to me that filter_compatible_signatures + # should fail here, on incompatible signatures; but that's + # what we have it doing currently. Revisit. + siglist = filter_compatible_signatures(query, siglist, False) + siglist = list(siglist) + except ValueError: + siglist = [] + if not siglist: notify("no compatible signatures found in '{}'", filename) sys.exit(-1) diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index 71b5ebec66..224602a06c 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -859,8 +859,8 @@ def test_compare_no_matching_sigs(c): query = utils.get_test_data('lca/TARA_ASE_MAG_00031.sig') with pytest.raises(ValueError) as exc: - c.last_result.status, c.last_result.out, c.last_result.err = c.run_sourmash('compare', '-k', '100', query, - fail_ok=True) + c.last_result.status, c.last_result.out, c.last_result.err = \ + c.run_sourmash('compare', '-k', '100', query, fail_ok=True) print(c.last_result.out) print(c.last_result.err) @@ -1600,6 +1600,37 @@ def test_search_metagenome_traverse_check_csv(): assert '13 matches; showing first 3:' in out +@utils.in_thisdir +def test_search_incompatible(c): + num_sig = utils.get_test_data('num/47.fa.sig') + scaled_sig = utils.get_test_data('47.fa.sig') + + with pytest.raises(ValueError) as exc: + c.run_sourmash("search", scaled_sig, num_sig, fail_ok=True) + assert c.last_result.status != 0 + print(c.last_result.out) + print(c.last_result.err) + assert 'incompatible - cannot compare.' in c.last_result.err + assert 'was calculated with --scaled,' in c.last_result.err + + +@utils.in_tempdir +def test_search_traverse_incompatible(c): + searchdir = c.output('searchme') + os.mkdir(searchdir) + + num_sig = utils.get_test_data('num/47.fa.sig') + scaled_sig = utils.get_test_data('47.fa.sig') + shutil.copyfile(num_sig, c.output('searchme/num.sig')) + shutil.copyfile(scaled_sig, c.output('searchme/scaled.sig')) + + c.run_sourmash("search", scaled_sig, c.output('searchme')) + print(c.last_result.out) + print(c.last_result.err) + assert 'incompatible - cannot compare.' in c.last_result.err + assert 'was calculated with --scaled,' in c.last_result.err + + # explanation: you cannot downsample a scaled SBT to match a scaled # signature, so make sure that when you try such a search, it fails! # (you *can* downsample a signature to match an SBT.) @@ -3319,6 +3350,23 @@ def test_gather_metagenome_traverse_check_csv(): 'NC_011294.1 Salmonella enterica subsp...' in out)) +@utils.in_tempdir +def test_gather_traverse_incompatible(c): + searchdir = c.output('searchme') + os.mkdir(searchdir) + + num_sig = utils.get_test_data('num/47.fa.sig') + scaled_sig = utils.get_test_data('47.fa.sig') + shutil.copyfile(num_sig, c.output('searchme/num.sig')) + shutil.copyfile(scaled_sig, c.output('searchme/scaled.sig')) + + c.run_sourmash("gather", scaled_sig, c.output('searchme')) + print(c.last_result.out) + print(c.last_result.err) + assert 'incompatible - cannot compare.' in c.last_result.err + assert 'was calculated with --scaled,' in c.last_result.err + + def test_gather_metagenome_output_unassigned(): with utils.TempDirectory() as location: testdata_glob = utils.get_test_data('gather/GCF_000195995*g') From 14891bd4af9a6da2fe8c0ea01bf32dfef4880017 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Tue, 9 Mar 2021 07:09:33 -0800 Subject: [PATCH 22/71] add filter to LinearIndex and MultiIndex --- src/sourmash/index.py | 28 ++++++++++++++++++++++------ src/sourmash/sourmash_args.py | 35 +++++++++++++---------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index a8cc322d55..a4b287b90f 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -152,13 +152,19 @@ def load(cls, location): return lidx def select(self, ksize=None, moltype=None): - def select_sigs(siglist, ksize, moltype): - for ss in siglist: - if (ksize is None or ss.minhash.ksize == ksize) and \ - (moltype is None or ss.minhash.moltype == moltype): - yield ss + def select_sigs(ss, ksize=ksize, moltype=moltype): + if (ksize is None or ss.minhash.ksize == ksize) and \ + (moltype is None or ss.minhash.moltype == moltype): + return True + + return self.filter(select_sigs) + + def filter(self, filter_fn): + siglist = [] + for ss in self._signatures: + if filter_fn(ss): + siglist.append(ss) - siglist=select_sigs(self._signatures, ksize, moltype) return LinearIndex(siglist, self.filename) @@ -206,6 +212,16 @@ def select(self, ksize=None, moltype=None): return MultiIndex(new_idx_list, new_src_list) + def filter(self, filter_fn): + new_idx_list = [] + new_src_list = [] + for idx, src in zip(self.index_list, self.source_list): + idx = idx.filter(filter_fn) + new_idx_list.append(idx) + new_src_list.append(src) + + return MultiIndex(new_idx_list, new_src_list) + def search(self, query, *args, **kwargs): # do the actual search: matches = [] diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index f0a8e5b3c5..8f8b1f7624 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -181,16 +181,7 @@ def traverse_find_sigs(filenames, yield_all_files=False): yield fullname -def filter_compatible_signatures(query, siglist, force=False): - for ss in siglist: - if check_signatures_are_compatible(query, ss): - yield ss - else: - if not force: - raise ValueError("incompatible signature") - - -def check_signatures_are_compatible(query, subject): +def _check_signatures_are_compatible(query, subject): # is one scaled, and the other not? cannot do search if query.minhash.scaled and not subject.minhash.scaled or \ not query.minhash.scaled and subject.minhash.scaled: @@ -280,7 +271,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) assert dbtype == DatabaseType.SIGLIST db = db.select(moltype=query_moltype, ksize=query_ksize) - # @CTB filter compatible signatures here, too. write test. + filter_fn = lambda s: _check_signatures_are_compatible(query, s) + db = db.filter(filter_fn) if not db: notify("no compatible signatures found in '{}'", filename) sys.exit(-1) @@ -315,21 +307,20 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) # CTB: it's not clear to me that filter_compatible_signatures # should fail here, on incompatible signatures; but that's # what we have it doing currently. Revisit. - siglist = filter_compatible_signatures(query, siglist, False) - siglist = list(siglist) + filter_fn = lambda s: _check_signatures_are_compatible(query, + s) + db = db.filter(filter_fn) except ValueError: - siglist = [] + db = None - if not siglist: - notify("no compatible signatures found in '{}'", filename) + if not db: + notify(f"no compatible signatures found in '{filename}'") sys.exit(-1) - linear = LinearIndex(siglist, filename=filename) - databases.append(linear) + databases.append(db) - notify('loaded {} signatures from {}', len(linear), - filename, end='\r') - n_signatures += len(linear) + notify(f'loaded {len(db)} signatures from {filename}', end='\r') + n_signatures += len(db) # unknown!? else: @@ -402,7 +393,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): if not loaded: try: with open(filename, 'rt') as fp: - db = LinearIndex.load(fp) + db = LinearIndex.load(filename) dbtype = DatabaseType.SIGLIST loaded = True except Exception as exc: From 40395ffe85e82ff92ed5c350bc7fc53bb9140294 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Tue, 9 Mar 2021 07:17:36 -0800 Subject: [PATCH 23/71] clean up sourmash_args some more --- src/sourmash/sourmash_args.py | 39 ++++++----------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 8f8b1f7624..4766fe7664 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -266,21 +266,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) sys.exit(-1) # are we collecting signatures from a directory/path? - if os.path.isdir(filename): - # CTB: combine with SIGLIST below? - assert dbtype == DatabaseType.SIGLIST - - db = db.select(moltype=query_moltype, ksize=query_ksize) - filter_fn = lambda s: _check_signatures_are_compatible(query, s) - db = db.filter(filter_fn) - if not db: - notify("no compatible signatures found in '{}'", filename) - sys.exit(-1) - databases.append(db) - n_signatures += len(db) - - # SBT - elif dbtype == DatabaseType.SBT: + if dbtype == DatabaseType.SBT: if not check_tree_is_compatible(filename, db, query, is_similarity_query): sys.exit(-1) @@ -303,15 +289,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) elif dbtype == DatabaseType.SIGLIST: db = db.select(moltype=query_moltype, ksize=query_ksize) siglist = db.signatures() - try: - # CTB: it's not clear to me that filter_compatible_signatures - # should fail here, on incompatible signatures; but that's - # what we have it doing currently. Revisit. - filter_fn = lambda s: _check_signatures_are_compatible(query, - s) - db = db.filter(filter_fn) - except ValueError: - db = None + filter_fn = lambda s: _check_signatures_are_compatible(query, s) + db = db.filter(filter_fn) if not db: notify(f"no compatible signatures found in '{filename}'") @@ -369,7 +348,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): dbtype = DatabaseType.SIGLIST loaded = True - # load signatures from directory + # load signatures from directory, using MultiIndex to preserve source. if not loaded and os.path.isdir(filename): index_list = [] source_list = [] @@ -400,6 +379,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): pass # try load signatures from single file (list of signature paths) + # use MultiIndex to preserve source filenames. if not loaded: try: idx_list = [] @@ -458,14 +438,6 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): return db, dbtype -# note: dup from index.py internal function. -def _select_sigs(siglist, ksize, moltype): - for ss in siglist: - if (ksize is None or ss.minhash.ksize == ksize) and \ - (moltype is None or ss.minhash.moltype == moltype): - yield ss - - def load_file_as_index(filename, yield_all_files=False): """Load 'filename' as a database; generic database loader. @@ -512,6 +484,7 @@ def load_file_as_signatures(filename, select_moltype=None, ksize=None, else: return loader + def load_file_list_of_signatures(filename): "Load a list-of-files text file." try: From f377dc4764e85d89011a460aa4c54b84f6a85569 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 24 Mar 2021 08:28:00 -0700 Subject: [PATCH 24/71] shift loading over to Index classes --- src/sourmash/index.py | 42 +++++++++++++++++++++++++++++++++ src/sourmash/sourmash_args.py | 44 +++++++++++------------------------ 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 07e9c21b6a..3d2ff67c21 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -2,6 +2,7 @@ from abc import abstractmethod, ABC from collections import namedtuple +import os class Index(ABC): @@ -203,6 +204,47 @@ def insert(self, *args): def load(self, *args): raise NotImplementedError + @classmethod + def load_from_directory(cls, dirname, traverse_yield_all): + from .sourmash_args import traverse_find_sigs + if not os.path.isdir(dirname): + raise ValueError(f"'{dirname}' must be a directory") + + index_list = [] + source_list = [] + for thisfile in traverse_find_sigs([dirname], traverse_yield_all): + try: + idx = LinearIndex.load(thisfile) + index_list.append(idx) + source_list.append(thisfile) + except (IOError, sourmash.exceptions.SourmashError): + if traverse_yield_all: + continue + else: + raise + + db = None + if index_list: + db = cls(index_list, source_list) + + return db + + @classmethod + def load_from_file_list(cls, filename): + idx_list = [] + src_list = [] + + file_list = load_file_list_of_signatures(filename) + for fname in file_list: + idx = load_file_as_index(fname) + src = fname + + idx_list.append(idx) + src_list.append(src) + + db = MultiIndex(idx_list, src_list) + return db + def save(self, *args): raise NotImplementedError diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 5a3358783c..c6ad9125e3 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -73,6 +73,7 @@ def load_query_signature(filename, ksize, select_moltype, select_md5=None): sl = list(sl) except (OSError, ValueError): error("Cannot open file '{}'", filename) + raise sys.exit(-1) if len(sl) and select_md5: @@ -342,6 +343,8 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): loaded = False dbtype = None + print('XXX', filename) + # special case stdin if not loaded and filename == '-': db = LinearIndex.load(sys.stdin) @@ -349,30 +352,20 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): loaded = True # load signatures from directory, using MultiIndex to preserve source. - if not loaded and os.path.isdir(filename): - index_list = [] - source_list = [] - for thisfile in traverse_find_sigs([filename], traverse_yield_all): - try: - idx = LinearIndex.load(thisfile) - index_list.append(idx) - source_list.append(thisfile) - except (IOError, sourmash.exceptions.SourmashError): - if traverse_yield_all: - continue - else: - raise - - if index_list: - loaded=True - db = MultiIndex(index_list, source_list) + if not loaded: + try: + db = MultiIndex.load_from_directory(filename, traverse_yield_all) dbtype = DatabaseType.SIGLIST + loaded = True + except Exception as exc: + import traceback + traceback.print_exc() + pass # load signatures from single signature file if not loaded: try: - with open(filename, 'rt') as fp: - db = LinearIndex.load(filename) + db = LinearIndex.load(filename) dbtype = DatabaseType.SIGLIST loaded = True except Exception as exc: @@ -382,18 +375,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): # use MultiIndex to preserve source filenames. if not loaded: try: - idx_list = [] - src_list = [] - - file_list = load_file_list_of_signatures(filename) - for fname in file_list: - idx = load_file_as_index(fname) - src = fname - - idx_list.append(idx) - src_list.append(src) - - db = MultiIndex(idx_list, src_list) + db = MultiIndex.load_from_file_list(filename) dbtype = DatabaseType.SIGLIST loaded = True except Exception as exc: From 250c49a0b04972e36f4d2dc5ab9e57875234160b Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 24 Mar 2021 08:43:38 -0700 Subject: [PATCH 25/71] refactor, fix tests --- src/sourmash/index.py | 4 ++++ src/sourmash/sig/__main__.py | 2 +- src/sourmash/sourmash_args.py | 8 +++++--- tests/test_cmd_signature.py | 3 +++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 3d2ff67c21..b17a51d6f3 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -226,11 +226,15 @@ def load_from_directory(cls, dirname, traverse_yield_all): db = None if index_list: db = cls(index_list, source_list) + else: + raise ValueError(f"no signatures to load under directory '{dirname}'") return db @classmethod def load_from_file_list(cls, filename): + from .sourmash_args import (load_file_list_of_signatures, + load_file_as_index) idx_list = [] src_list = [] diff --git a/src/sourmash/sig/__main__.py b/src/sourmash/sig/__main__.py index 75f738ab14..076a3412b1 100644 --- a/src/sourmash/sig/__main__.py +++ b/src/sourmash/sig/__main__.py @@ -73,10 +73,10 @@ def cat(args): siglist = [] for sigfile in args.signatures: this_siglist = [] + n_loaded = 0 try: loader = sourmash_args.load_file_as_signatures(sigfile, progress=progress) - n_loaded = 0 for sig in loader: n_loaded += 1 diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index c6ad9125e3..29c9c3bd6e 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -343,7 +343,8 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): loaded = False dbtype = None - print('XXX', filename) + # @CTB add debug/more informative error messages if we're going to + # catch all exceptions. Or, standardize on ValueError or something. # special case stdin if not loaded and filename == '-': @@ -358,8 +359,6 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): dbtype = DatabaseType.SIGLIST loaded = True except Exception as exc: - import traceback - traceback.print_exc() pass # load signatures from single signature file @@ -417,6 +416,9 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): if not loaded: raise OSError(f"Error while reading signatures from '{filename}'.") + if loaded: + assert db + return db, dbtype diff --git a/tests/test_cmd_signature.py b/tests/test_cmd_signature.py index 4152ceab33..07e343f707 100644 --- a/tests/test_cmd_signature.py +++ b/tests/test_cmd_signature.py @@ -778,6 +778,9 @@ def test_sig_cat_filelist_with_dbs(c): c.run_sourmash('sig', 'cat', filelist, '-o', 'out.sig') + print(c.last_result.out) + print(c.last_result.err) + # stdout should be same signatures out = c.output('out.sig') From 9a921f97e7ee75e5833d0c57d9c31554d94c1d2c Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Thu, 25 Mar 2021 10:06:23 -0700 Subject: [PATCH 26/71] switch to a list of loader functions --- src/sourmash/sourmash_args.py | 123 +++++++++++++++++++++------------- tests/test_api.py | 4 +- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 29c9c3bd6e..b4a8e80cf0 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -6,6 +6,7 @@ import argparse import itertools from enum import Enum +import traceback import screed @@ -14,7 +15,7 @@ import sourmash.exceptions from . import signature -from .logging import notify, error +from .logging import notify, error, debug from .index import LinearIndex, MultiIndex from . import signature as sig @@ -73,7 +74,7 @@ def load_query_signature(filename, ksize, select_moltype, select_md5=None): sl = list(sl) except (OSError, ValueError): error("Cannot open file '{}'", filename) - raise + raise # @CTB testme? sys.exit(-1) if len(sl) and select_md5: @@ -333,6 +334,68 @@ class DatabaseType(Enum): LCA = 3 +def _load_stdin(filename, **kwargs): + db = None + if filename == '-': + db = LinearIndex.load(sys.stdin) + + return (db, DatabaseType.SIGLIST) + + +def _multiindex_load_from_file_list(filename, **kwargs): + try: + db = MultiIndex.load_from_file_list(filename) + except UnicodeDecodeError as exc: + raise ValueError(exc) + + return (db, DatabaseType.SIGLIST) + + +def _multiindex_load_from_directory(filename, **kwargs): + traverse_yield_all = kwargs['traverse_yield_all'] + db = MultiIndex.load_from_directory(filename, traverse_yield_all) + + return (db, DatabaseType.SIGLIST) + +def _load_sigfile(filename, **kwargs): + try: + db = LinearIndex.load(filename) + except sourmash.exceptions.SerdeError as exc: + raise ValueError(exc) + except FileNotFoundError: + raise ValueError(f"Error while reading signatures from '{filename}'") + except Exception as exc: + raise ValueError(f"Error while reading signatures from '{filename}'") + #raise ValueError(exc) # load_signature line 255 raises general exc @CTB + return (db, DatabaseType.SIGLIST) + + +def _load_sbt(filename, **kwargs): + cache_size = kwargs.get('cache_size') + + try: + db = load_sbt_index(filename, cache_size=cache_size) + except FileNotFoundError as exc: + raise ValueError(exc) + + return (db, DatabaseType.SBT) + + +def _load_revindex(filename, **kwargs): + db, _, _ = load_single_database(filename) + return (db, DatabaseType.LCA) + + +_loader_functions = [ + ("load from stdin", _load_stdin), + ("load from directory", _multiindex_load_from_directory), + ("load from sig file", _load_sigfile), + ("load from file list", _multiindex_load_from_file_list), + ("load SBT", _load_sbt), + ("load revindex", _load_revindex), + ] + + def _load_database(filename, traverse_yield_all, *, cache_size=None): """Load file as a database - list of signatures, LCA, SBT, etc. @@ -346,55 +409,23 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): # @CTB add debug/more informative error messages if we're going to # catch all exceptions. Or, standardize on ValueError or something. - # special case stdin - if not loaded and filename == '-': - db = LinearIndex.load(sys.stdin) - dbtype = DatabaseType.SIGLIST - loaded = True - - # load signatures from directory, using MultiIndex to preserve source. - if not loaded: + for (desc, load_fn) in _loader_functions: + #print(f"trying loader fn {desc} for {filename}", file=sys.stderr) try: - db = MultiIndex.load_from_directory(filename, traverse_yield_all) - dbtype = DatabaseType.SIGLIST - loaded = True - except Exception as exc: + db, dbtype = load_fn(filename, + traverse_yield_all=traverse_yield_all, + cache_size=cache_size) + except ValueError as exc: + #print(f"FAIL load {desc}", file=sys.stderr) pass - - # load signatures from single signature file - if not loaded: - try: - db = LinearIndex.load(filename) - dbtype = DatabaseType.SIGLIST - loaded = True except Exception as exc: - pass + #print(f"FAIL load {desc}", file=sys.stderr) + #print(traceback.format_exc(), file=sys.stderr) + raise - # try load signatures from single file (list of signature paths) - # use MultiIndex to preserve source filenames. - if not loaded: - try: - db = MultiIndex.load_from_file_list(filename) - dbtype = DatabaseType.SIGLIST + if db: loaded = True - except Exception as exc: - pass - - if not loaded: # try load as SBT - try: - db = load_sbt_index(filename, cache_size=cache_size) - loaded = True - dbtype = DatabaseType.SBT - except: - pass - - if not loaded: # try load as LCA - try: - db, _, _ = load_single_database(filename) - loaded = True - dbtype = DatabaseType.LCA - except: - pass + break # check to see if it's a FASTA/FASTQ record (i.e. screed loadable) # so we can provide a better error message to users. diff --git a/tests/test_api.py b/tests/test_api.py index a6c298d3c3..4e5930b193 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -20,9 +20,9 @@ def test_sourmash_signature_api(c): @utils.in_tempdir def test_load_index_0_no_file(c): - with pytest.raises(OSError) as exc: + with pytest.raises(Exception) as exc: # @CTB fix exception type idx = sourmash.load_file_as_index(c.output('does-not-exist')) - assert 'Error while reading signatures from ' in str(exc.value) + assert 'Error ' in str(exc.value) # @CTB fixme def test_load_index_1(): From 780fb716ba3b53ea7141f3c60a9fa0120cb3600a Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 09:53:30 -0700 Subject: [PATCH 27/71] comments, docstrings, and tests passing --- src/sourmash/lca/lca_db.py | 5 ++++- src/sourmash/sig/__main__.py | 2 +- src/sourmash/sourmash_args.py | 23 +++++++++++++++++++---- tests/test_cmd_signature.py | 3 +++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index 9c305c80b4..137f0fbd5c 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -1,5 +1,5 @@ "LCA database class and utilities." - +import os import json import gzip from collections import OrderedDict, defaultdict, Counter @@ -187,6 +187,9 @@ def load(cls, db_name): "Load LCA_Database from a JSON file." from .lca_utils import taxlist, LineagePair + if not os.path.isfile(db_name): + raise ValueError(f"'{db_name}' is not a file and cannot be loaded as an LCA database") + xopen = open if db_name.endswith('.gz'): xopen = gzip.open diff --git a/src/sourmash/sig/__main__.py b/src/sourmash/sig/__main__.py index 076a3412b1..e39f54d3a9 100644 --- a/src/sourmash/sig/__main__.py +++ b/src/sourmash/sig/__main__.py @@ -73,7 +73,7 @@ def cat(args): siglist = [] for sigfile in args.signatures: this_siglist = [] - n_loaded = 0 + n_loaded = 0 # @CTB testme. try: loader = sourmash_args.load_file_as_signatures(sigfile, progress=progress) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index b4a8e80cf0..c70efd52ec 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -259,11 +259,12 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) n_databases = 0 databases = [] for filename in filenames: - notify('loading from {}...', filename, end='\r') + notify(f'loading from {filename}...', end='\r') try: db, dbtype = _load_database(filename, False, cache_size=cache_size) except IOError as e: + raise notify(str(e)) sys.exit(-1) @@ -335,6 +336,7 @@ class DatabaseType(Enum): def _load_stdin(filename, **kwargs): + "Load collection from .sig file streamed in via stdin" db = None if filename == '-': db = LinearIndex.load(sys.stdin) @@ -343,6 +345,7 @@ def _load_stdin(filename, **kwargs): def _multiindex_load_from_file_list(filename, **kwargs): + "Load collection from a list of signature/database files" try: db = MultiIndex.load_from_file_list(filename) except UnicodeDecodeError as exc: @@ -352,12 +355,15 @@ def _multiindex_load_from_file_list(filename, **kwargs): def _multiindex_load_from_directory(filename, **kwargs): + "Load collection from a directory." traverse_yield_all = kwargs['traverse_yield_all'] db = MultiIndex.load_from_directory(filename, traverse_yield_all) return (db, DatabaseType.SIGLIST) + def _load_sigfile(filename, **kwargs): + "Load collection from a signature JSON file" try: db = LinearIndex.load(filename) except sourmash.exceptions.SerdeError as exc: @@ -371,6 +377,7 @@ def _load_sigfile(filename, **kwargs): def _load_sbt(filename, **kwargs): + "Load collection from an SBT." cache_size = kwargs.get('cache_size') try: @@ -382,10 +389,15 @@ def _load_sbt(filename, **kwargs): def _load_revindex(filename, **kwargs): - db, _, _ = load_single_database(filename) + "Load collection from an LCA database/reverse index." + try: + db, _, _ = load_single_database(filename) + except FileNotFoundError as exc: + raise ValueError(exc) return (db, DatabaseType.LCA) +# all loader functions, in order. _loader_functions = [ ("load from stdin", _load_stdin), ("load from directory", _multiindex_load_from_directory), @@ -505,10 +517,13 @@ def load_file_list_of_signatures(filename): try: with open(filename, 'rt') as fp: file_list = [ x.rstrip('\r\n') for x in fp ] + + if not os.path.exists(file_list[0]): + raise ValueError("first element of list-of-files does not exist") except OSError: - raise ValueError("cannot open file '{}'".format(filename)) + raise ValueError(f"cannot open file '{filename}'") except UnicodeDecodeError: - raise ValueError("cannot parse file '{}' as list of filenames".format(filename)) + raise ValueError(f"cannot parse file '{filename}' as list of filenames") return file_list diff --git a/tests/test_cmd_signature.py b/tests/test_cmd_signature.py index 07e343f707..2dd0cac078 100644 --- a/tests/test_cmd_signature.py +++ b/tests/test_cmd_signature.py @@ -625,6 +625,9 @@ def test_sig_rename_3_file_dne(c): with pytest.raises(ValueError) as e: c.run_sourmash('sig', 'rename', 'no-such-sig', 'fiz bar') + print('out', (c.last_result.out,)) + print('err', (c.last_result.err,)) + assert "Error while reading signatures from 'no-such-sig'" in c.last_result.err From d2619636b3eeecdc1cb02e3b8ea76700f4efc0a4 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 10:19:23 -0700 Subject: [PATCH 28/71] update to use f strings throughout sourmash_args.py --- src/sourmash/sourmash_args.py | 59 ++++++++++++++--------------------- tests/test_api.py | 6 ++-- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index c70efd52ec..9012e7d66c 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -25,7 +25,6 @@ import sourmash DEFAULT_LOAD_K = 31 -DEFAULT_N = 500 def get_moltype(sig, require=False): @@ -84,8 +83,7 @@ def load_query_signature(filename, ksize, select_moltype, select_md5=None): if sig_md5.startswith(select_md5.lower()): # make sure we pick only one -- if found_sig is not None: - error("Error! Multiple signatures start with md5 '{}'", - select_md5) + error(f"Error! Multiple signatures start with md5 '{select_md5}'") error("Please use a longer --md5 selector.") sys.exit(-1) else: @@ -98,16 +96,16 @@ def load_query_signature(filename, ksize, select_moltype, select_md5=None): if len(ksizes) == 1: ksize = ksizes.pop() sl = [ ss for ss in sl if ss.minhash.ksize == ksize ] - notify('select query k={} automatically.', ksize) + notify(f'select query k={ksize} automatically.') elif DEFAULT_LOAD_K in ksizes: sl = [ ss for ss in sl if ss.minhash.ksize == DEFAULT_LOAD_K ] - notify('selecting default query k={}.', DEFAULT_LOAD_K) + notify(f'selecting default query k={DEFAULT_LOAD_K}.') elif ksize: - notify('selecting specified query k={}', ksize) + notify(f'selecting specified query k={ksize}') if len(sl) != 1: - error('When loading query from "{}"', filename) - error('{} signatures matching ksize and molecule type;', len(sl)) + error(f"When loading query from '{filename}'", filename) + error(f'{len(sl)} signatures matching ksize and molecule type;') error('need exactly one. Specify --ksize or --dna, --rna, or --protein.') sys.exit(-1) @@ -190,11 +188,9 @@ def _check_signatures_are_compatible(query, subject): error("signature {} and {} are incompatible - cannot compare.", query, subject) if query.minhash.scaled: - error("{} was calculated with --scaled, {} was not.", - query, subject) + error(f"{query} was calculated with --scaled, {subject} was not.") if subject.minhash.scaled: - error("{} was calculated with --scaled, {} was not.", - subject, query) + error(f"{subject} was calculated with --scaled, {query} was not.") return 0 return 1 @@ -208,15 +204,14 @@ def check_tree_is_compatible(treename, tree, query, is_similarity_query): query_mh = query.minhash if tree_mh.ksize != query_mh.ksize: - error("ksize on tree '{}' is {};", treename, tree_mh.ksize) - error('this is different from query ksize of {}.', query_mh.ksize) + error(f"ksize on tree '{treename}' is {tree_mh.ksize};") + error(f"this is different from query ksize of {query_mh.ksize}.") return 0 # is one scaled, and the other not? cannot do search. if (tree_mh.scaled and not query_mh.scaled) or \ (query_mh.scaled and not tree_mh.scaled): - error("for tree '{}', tree and query are incompatible for search.", - treename) + error(f"for tree '{treename}', tree and query are incompatible for search.") if tree_mh.scaled: error("tree was calculated with scaled, query was not.") else: @@ -226,9 +221,8 @@ def check_tree_is_compatible(treename, tree, query, is_similarity_query): # are the scaled values incompatible? cannot downsample tree for similarity if tree_mh.scaled and tree_mh.scaled < query_mh.scaled and \ is_similarity_query: - error("for tree '{}', scaled value is smaller than query.", treename) - error("tree scaled: {}; query scaled: {}. Cannot do similarity search.", - tree_mh.scaled, query_mh.scaled) + error(f"for tree '{treename}', scaled value is smaller than query.") + error(f"tree scaled: {tree_mh.scaled}; query scaled: {query_mh.scaled}. Cannot do similarity search.") return 0 return 1 @@ -237,8 +231,8 @@ def check_tree_is_compatible(treename, tree, query, is_similarity_query): def check_lca_db_is_compatible(filename, db, query): query_mh = query.minhash if db.ksize != query_mh.ksize: - error("ksize on db '{}' is {};", filename, db.ksize) - error('this is different from query ksize of {}.', query_mh.ksize) + error(f"ksize on db '{filename}' is {db.ksize};") + error(f"this is different from query ksize of {query_mh.ksize}.") return 0 return 1 @@ -275,7 +269,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) sys.exit(-1) databases.append(db) - notify('loaded SBT {}', filename, end='\r') + notify(f'loaded SBT {filename}', end='\r') n_databases += 1 # LCA @@ -283,7 +277,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) if not check_lca_db_is_compatible(filename, db, query): sys.exit(-1) - notify('loaded LCA {}', filename, end='\r') + notify('loaded LCA {filename}', end='\r') n_databases += 1 databases.append(db) @@ -306,19 +300,18 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) # unknown!? else: - raise Exception("unknown dbtype {}".format(dbtype)) + raise ValueError("unknown dbtype {dbtype}") # END for loop notify(' '*79, end='\r') if n_signatures and n_databases: - notify('loaded {} signatures and {} databases total.', n_signatures, - n_databases) + notify(f'loaded {n_signatures} signatures and {n_databases} databases total.') elif n_signatures: - notify('loaded {} signatures.', n_signatures) + notify(f'loaded {n_signatures} signatures.') elif n_databases: - notify('loaded {} databases.', n_databases) + notify(f'loaded {n_databases} databases.') else: notify('** ERROR: no signatures or databases loaded?') sys.exit(-1) @@ -430,10 +423,6 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): except ValueError as exc: #print(f"FAIL load {desc}", file=sys.stderr) pass - except Exception as exc: - #print(f"FAIL load {desc}", file=sys.stderr) - #print(traceback.format_exc(), file=sys.stderr) - raise if db: loaded = True @@ -454,12 +443,12 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): pass if successful_screed_load: - raise OSError("Error while reading signatures from '{}' - got sequences instead! Is this a FASTA/FASTQ file?".format(filename)) + raise ValueError(f"Error while reading signatures from '{filename}' - got sequences instead! Is this a FASTA/FASTQ file?") if not loaded: - raise OSError(f"Error while reading signatures from '{filename}'.") + raise ValueError(f"Error while reading signatures from '{filename}'.") - if loaded: + if loaded: # this is a bit redundant but safe > sorry assert db return db, dbtype diff --git a/tests/test_api.py b/tests/test_api.py index 4e5930b193..b9f24fc385 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -53,7 +53,9 @@ def test_load_fasta_as_signature(): # try loading a fasta file - should fail with informative exception testfile = utils.get_test_data('short.fa') - with pytest.raises(OSError) as e: + with pytest.raises(ValueError) as exc: idx = sourmash.load_file_as_index(testfile) - assert "Error while reading signatures from '{}' - got sequences instead! Is this a FASTA/FASTQ file?".format(testfile) in str(e) + print(exc.value) + + assert f"Error while reading signatures from '{testfile}' - got sequences instead! Is this a FASTA/FASTQ file?" in str(exc.value) From 93fca04823d1ecd31ac965bc073572d309c8d010 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 10:23:15 -0700 Subject: [PATCH 29/71] add docstrings --- src/sourmash/index.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index b17a51d6f3..8b62d5c23b 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -206,6 +206,7 @@ def load(self, *args): @classmethod def load_from_directory(cls, dirname, traverse_yield_all): + "Create a MultiIndex from all files under a directory." from .sourmash_args import traverse_find_sigs if not os.path.isdir(dirname): raise ValueError(f"'{dirname}' must be a directory") @@ -233,6 +234,7 @@ def load_from_directory(cls, dirname, traverse_yield_all): @classmethod def load_from_file_list(cls, filename): + "Create a MultiIndex from all files listed in a text file." from .sourmash_args import (load_file_list_of_signatures, load_file_as_index) idx_list = [] From 020335775a7c71abf7343d97465b4695daca0426 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 10:27:46 -0700 Subject: [PATCH 30/71] update comments --- src/sourmash/sourmash_args.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 9012e7d66c..fab04dd477 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -245,6 +245,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) Check for compatibility with query. This is basically a user-focused wrapping of _load_databases. + + @CTB this can be refactored into a more generic function with 'filter'. """ query_ksize = query.minhash.ksize query_moltype = get_moltype(query) @@ -262,7 +264,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(str(e)) sys.exit(-1) - # are we collecting signatures from a directory/path? + # are we collecting signatures from an SBT? if dbtype == DatabaseType.SBT: if not check_tree_is_compatible(filename, db, query, is_similarity_query): @@ -272,7 +274,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(f'loaded SBT {filename}', end='\r') n_databases += 1 - # LCA + # or an LCA? elif dbtype == DatabaseType.LCA: if not check_lca_db_is_compatible(filename, db, query): sys.exit(-1) @@ -282,7 +284,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) databases.append(db) - # signature file + # or a mixed collection of signatures? elif dbtype == DatabaseType.SIGLIST: db = db.select(moltype=query_moltype, ksize=query_ksize) siglist = db.signatures() @@ -300,7 +302,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) # unknown!? else: - raise ValueError("unknown dbtype {dbtype}") + raise ValueError(f"unknown dbtype {dbtype}") # @CTB test? # END for loop From 8a0200a491ef2b6b4679592bd4e2c6dcec064233 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 12:16:24 -0700 Subject: [PATCH 31/71] remove unnecessary changes --- tests/test_cmd_signature.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_cmd_signature.py b/tests/test_cmd_signature.py index 2dd0cac078..4152ceab33 100644 --- a/tests/test_cmd_signature.py +++ b/tests/test_cmd_signature.py @@ -625,9 +625,6 @@ def test_sig_rename_3_file_dne(c): with pytest.raises(ValueError) as e: c.run_sourmash('sig', 'rename', 'no-such-sig', 'fiz bar') - print('out', (c.last_result.out,)) - print('err', (c.last_result.err,)) - assert "Error while reading signatures from 'no-such-sig'" in c.last_result.err @@ -781,9 +778,6 @@ def test_sig_cat_filelist_with_dbs(c): c.run_sourmash('sig', 'cat', filelist, '-o', 'out.sig') - print(c.last_result.out) - print(c.last_result.err) - # stdout should be same signatures out = c.output('out.sig') From e9df90f0a49e47d71903603d78544907415688c0 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 12:18:23 -0700 Subject: [PATCH 32/71] revert to original test --- tests/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index b9f24fc385..b2f994751a 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -20,9 +20,9 @@ def test_sourmash_signature_api(c): @utils.in_tempdir def test_load_index_0_no_file(c): - with pytest.raises(Exception) as exc: # @CTB fix exception type + with pytest.raises(ValueError) as exc: # @CTB fix exception type idx = sourmash.load_file_as_index(c.output('does-not-exist')) - assert 'Error ' in str(exc.value) # @CTB fixme + assert 'Error while reading signatures from ' in str(exc.value) def test_load_index_1(): From 9e427e32778440393c3fe6ffa5cfee6c3f9b1eb3 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 12:18:56 -0700 Subject: [PATCH 33/71] remove unneeded comment --- tests/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api.py b/tests/test_api.py index b2f994751a..3291c62165 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -20,7 +20,7 @@ def test_sourmash_signature_api(c): @utils.in_tempdir def test_load_index_0_no_file(c): - with pytest.raises(ValueError) as exc: # @CTB fix exception type + with pytest.raises(ValueError) as exc: idx = sourmash.load_file_as_index(c.output('does-not-exist')) assert 'Error while reading signatures from ' in str(exc.value) From 0dd390a92ea401a02518c54f236617078c69e82f Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Fri, 26 Mar 2021 12:21:42 -0700 Subject: [PATCH 34/71] clean up a bit --- src/sourmash/sourmash_args.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 5cf5ecc2bd..1a4c67fd9b 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -367,7 +367,7 @@ def _load_sigfile(filename, **kwargs): raise ValueError(f"Error while reading signatures from '{filename}'") except Exception as exc: raise ValueError(f"Error while reading signatures from '{filename}'") - #raise ValueError(exc) # load_signature line 255 raises general exc @CTB + #raise ValueError(exc) # load_signature line 255 raises general exc @CTB fixme return (db, DatabaseType.SIGLIST) @@ -413,17 +413,14 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): loaded = False dbtype = None - # @CTB add debug/more informative error messages if we're going to - # catch all exceptions. Or, standardize on ValueError or something. - + # iterate through loader functions, trying them all. Catch ValueError + # but nothing else. for (desc, load_fn) in _loader_functions: - #print(f"trying loader fn {desc} for {filename}", file=sys.stderr) try: db, dbtype = load_fn(filename, traverse_yield_all=traverse_yield_all, cache_size=cache_size) except ValueError as exc: - #print(f"FAIL load {desc}", file=sys.stderr) pass if db: From 2c0ee2986fa8f6eaaf8466f7793d252caed5e798 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 27 Mar 2021 07:25:48 -0700 Subject: [PATCH 35/71] debugging update --- src/sourmash/sourmash_args.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 1a4c67fd9b..b99601fff8 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -302,7 +302,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) # unknown!? else: - raise ValueError(f"unknown dbtype {dbtype}") # @CTB test? + raise ValueError(f"unknown dbtype {dbtype}") # CTB check me. # END for loop @@ -417,11 +417,13 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): # but nothing else. for (desc, load_fn) in _loader_functions: try: + debug(f"_load_databases: trying loader fn {desc}") db, dbtype = load_fn(filename, traverse_yield_all=traverse_yield_all, cache_size=cache_size) except ValueError as exc: - pass + debug(f"_load_databases: FAIL on fn {desc}.") + debug(traceback.format_exc()) if db: loaded = True From edcb483b4b7cd4426fc5ecdffceda613087bc6a5 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 27 Mar 2021 07:30:06 -0700 Subject: [PATCH 36/71] better exception raising and capture for signature parsing --- src/sourmash/signature.py | 2 +- src/sourmash/sourmash_args.py | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/sourmash/signature.py b/src/sourmash/signature.py index 60bb2d5c90..e382e58311 100644 --- a/src/sourmash/signature.py +++ b/src/sourmash/signature.py @@ -252,7 +252,7 @@ def load_signatures( input_type = _detect_input_type(data) if input_type == SigInput.UNKNOWN: if do_raise: - raise Exception("Error in parsing signature; quitting. Cannot open file or invalid signature") + raise ValueError("Error in parsing signature; quitting. Cannot open file or invalid signature") return size = ffi.new("uintptr_t *") diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index b99601fff8..486a2a7ffa 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -246,7 +246,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) This is basically a user-focused wrapping of _load_databases. - @CTB this can be refactored into a more generic function with 'filter'. + CTB: this can be refactored into a more generic function with 'filter'. """ query_ksize = query.minhash.ksize query_moltype = get_moltype(query) @@ -361,13 +361,11 @@ def _load_sigfile(filename, **kwargs): "Load collection from a signature JSON file" try: db = LinearIndex.load(filename) - except sourmash.exceptions.SerdeError as exc: + except sourmash.exceptions.SourmashError as exc: raise ValueError(exc) except FileNotFoundError: raise ValueError(f"Error while reading signatures from '{filename}'") - except Exception as exc: - raise ValueError(f"Error while reading signatures from '{filename}'") - #raise ValueError(exc) # load_signature line 255 raises general exc @CTB fixme + return (db, DatabaseType.SIGLIST) From 3f6c3f21c3311a12a1e1c658230b4390ecf0399d Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 27 Mar 2021 07:35:02 -0700 Subject: [PATCH 37/71] more specific error message --- src/sourmash/sourmash_args.py | 3 +-- tests/test_sourmash.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 486a2a7ffa..b0720a5f07 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -72,8 +72,7 @@ def load_query_signature(filename, ksize, select_moltype, select_md5=None): select_moltype=select_moltype) sl = list(sl) except (OSError, ValueError): - error("Cannot open file '{}'", filename) - raise # @CTB testme? + error(f"Cannot open query file '{filename}'") sys.exit(-1) if len(sl) and select_md5: diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index a1f2b55f6e..1a0d1d4d65 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -716,7 +716,7 @@ def test_search_query_sig_does_not_exist(c): print(c.last_result.status, c.last_result.out, c.last_result.err) assert c.last_result.status == -1 - assert "Cannot open file 'short2.fa.sig'" in c.last_result.err + assert "Cannot open query file 'short2.fa.sig'" in c.last_result.err assert len(c.last_result.err.split('\n\r')) < 5 From 78dbb1d07d10168b5c7ed2c07ad171aea3c7e06f Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sat, 27 Mar 2021 07:41:58 -0700 Subject: [PATCH 38/71] revert change in favor of creating new issue --- src/sourmash/sig/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sourmash/sig/__main__.py b/src/sourmash/sig/__main__.py index e39f54d3a9..75f738ab14 100644 --- a/src/sourmash/sig/__main__.py +++ b/src/sourmash/sig/__main__.py @@ -73,10 +73,10 @@ def cat(args): siglist = [] for sigfile in args.signatures: this_siglist = [] - n_loaded = 0 # @CTB testme. try: loader = sourmash_args.load_file_as_signatures(sigfile, progress=progress) + n_loaded = 0 for sig in loader: n_loaded += 1 From 229b1d7f3e7c810ac7a9d8d43c3ad7c9d2fa0af1 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 08:41:03 -0700 Subject: [PATCH 39/71] add commentary => TODO --- src/sourmash/commands.py | 1 + src/sourmash/lca/command_summarize.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/sourmash/commands.py b/src/sourmash/commands.py index ff41e3e124..35b88d0610 100644 --- a/src/sourmash/commands.py +++ b/src/sourmash/commands.py @@ -534,6 +534,7 @@ def categorize(args): tree = load_sbt_index(args.sbt_name) # load query filenames + # @CTB replace with MultiIndex? inp_files = set(sourmash_args.traverse_find_sigs(args.queries)) inp_files = inp_files - already_names diff --git a/src/sourmash/lca/command_summarize.py b/src/sourmash/lca/command_summarize.py index d5d0765f03..e64cca8e01 100644 --- a/src/sourmash/lca/command_summarize.py +++ b/src/sourmash/lca/command_summarize.py @@ -67,6 +67,8 @@ def load_singletons_and_count(filenames, ksize, scaled, ignore_abundance): filenames = sourmash_args.traverse_find_sigs(filenames) filenames = list(filenames) + # @CTB replace with MultiIndex? + total_n = len(filenames) for query_filename in filenames: From 20ed9f0b91ecbb67f1e41fe141022e9ad5ac00d9 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 09:08:01 -0700 Subject: [PATCH 40/71] add tests for MultiIndex.load_from_directory; fix traverse code --- src/sourmash/index.py | 12 +-- src/sourmash/sourmash_args.py | 40 +++++----- tests/test_index.py | 137 ++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 24 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 8b62d5c23b..e6dd779b91 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -1,5 +1,6 @@ "An Abstract Base Class for collections of signatures." +import sourmash from abc import abstractmethod, ABC from collections import namedtuple import os @@ -205,7 +206,7 @@ def load(self, *args): raise NotImplementedError @classmethod - def load_from_directory(cls, dirname, traverse_yield_all): + def load_from_directory(cls, dirname, force=False): "Create a MultiIndex from all files under a directory." from .sourmash_args import traverse_find_sigs if not os.path.isdir(dirname): @@ -213,16 +214,17 @@ def load_from_directory(cls, dirname, traverse_yield_all): index_list = [] source_list = [] - for thisfile in traverse_find_sigs([dirname], traverse_yield_all): + for thisfile in traverse_find_sigs([dirname], + yield_all_files=force): try: idx = LinearIndex.load(thisfile) index_list.append(idx) source_list.append(thisfile) except (IOError, sourmash.exceptions.SourmashError): - if traverse_yield_all: - continue + if force: + continue # ignore error else: - raise + raise # contine past error! db = None if index_list: diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index b0720a5f07..84a63c7bfa 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -152,32 +152,34 @@ def __iter__(self): yield filename, query, query_moltype, query_ksize +def _check_suffix(filename, endings): + for ending in endings: + if filename.endswith(ending): + return True + return False + + def traverse_find_sigs(filenames, yield_all_files=False): + """Find all .sig and .sig.gz files in & beneath 'filenames'. + + By default, this function returns files with .sig and .sig.gz extensions. + If 'yield_all_files' is True, this will return _all_ files + (but not directories). + """ endings = ('.sig', '.sig.gz') for filename in filenames: + # check for files in filenames: if os.path.isfile(filename): - yield_me = False - if yield_all_files: - yield_me = True - continue - else: - for ending in endings: - if filename.endswith(ending): - yield_me = True - break - - if yield_me: + if yield_all_files or _check_suffix(filename, endings): yield filename - continue - - # filename is a directory -- - dirname = filename - for root, dirs, files in os.walk(dirname): - for name in files: - if name.endswith('.sig') or yield_all_files: + # filename is a directory -- traverse beneath! + elif os.path.isdir(filename): + for root, dirs, files in os.walk(filename): + for name in files: fullname = os.path.join(root, name) - yield fullname + if yield_all_files or _check_suffix(fullname, endings): + yield fullname def _check_signatures_are_compatible(query, subject): diff --git a/tests/test_index.py b/tests/test_index.py index 1b9ae93402..6530243a8b 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -1,6 +1,11 @@ +""" +Tests for Index classes and subclasses. +""" +import pytest import glob import os import zipfile +import shutil import sourmash from sourmash import load_one_signature, SourmashSignature @@ -502,3 +507,135 @@ def test_multi_index_signatures(): assert ss2 in siglist assert ss47 in siglist assert ss63 in siglist + + +def test_multi_index_load_from_directory(): + dirname = utils.get_test_data('prot/protein') + mi = MultiIndex.load_from_directory(dirname, force=False) + + sigs = list(mi.signatures()) + assert len(sigs) == 2 + + +def test_multi_index_load_from_directory_2(): + # only load .sig files, currently; not the databases under that directory. + dirname = utils.get_test_data('prot') + mi = MultiIndex.load_from_directory(dirname, force=False) + + print(mi.index_list) + print(mi.source_list) + + sigs = list(mi.signatures()) + assert len(sigs) == 6 + + +@utils.in_tempdir +def test_multi_index_load_from_directory_3(c): + # check that force works ok on a directory + dirname = utils.get_test_data('prot') + + count = 0 + for root, dirs, files in os.walk(dirname): + for name in files: + print(f"at {name}") + fullname = os.path.join(root, name) + copyto = c.output(f"file{count}.sig") + shutil.copyfile(fullname, copyto) + count += 1 + + with pytest.raises(sourmash.exceptions.SourmashError): + mi = MultiIndex.load_from_directory(c.location, force=False) + + +@utils.in_tempdir +def test_multi_index_load_from_directory_3_yield_all_true(c): + # check that force works ok on a directory w/force=True + dirname = utils.get_test_data('prot') + + count = 0 + for root, dirs, files in os.walk(dirname): + for name in files: + print(f"at {name}") + fullname = os.path.join(root, name) + copyto = c.output(f"file{count}.something") + shutil.copyfile(fullname, copyto) + count += 1 + + mi = MultiIndex.load_from_directory(c.location, force=True) + + print(mi.index_list) + print(mi.source_list) + + sigs = list(mi.signatures()) + assert len(sigs) == 6 + + +@utils.in_tempdir +def test_multi_index_load_from_directory_3_yield_all_true_subdir(c): + # check that force works ok on subdirectories + dirname = utils.get_test_data('prot') + + target_dir = c.output("some_subdir") + os.mkdir(target_dir) + + count = 0 + for root, dirs, files in os.walk(dirname): + for name in files: + print(f"at {name}") + fullname = os.path.join(root, name) + copyto = os.path.join(target_dir, f"file{count}.something") + shutil.copyfile(fullname, copyto) + count += 1 + + mi = MultiIndex.load_from_directory(c.location, force=True) + + print(mi.index_list) + print(mi.source_list) + + sigs = list(mi.signatures()) + assert len(sigs) == 6 + + +@utils.in_tempdir +def test_multi_index_load_from_directory_3_sig_gz(c): + # check that we find .sig.gz files, too + dirname = utils.get_test_data('prot') + + count = 0 + for root, dirs, files in os.walk(dirname): + for name in files: + if not name.endswith('.sig'): # skip non .sig things + continue + print(f"at {name}") + fullname = os.path.join(root, name) + copyto = c.output(f"file{count}.sig.gz") + shutil.copyfile(fullname, copyto) + count += 1 + + mi = MultiIndex.load_from_directory(c.location, force=False) + + print(mi.index_list) + print(mi.source_list) + + sigs = list(mi.signatures()) + assert len(sigs) == 6 + + +@utils.in_tempdir +def test_multi_index_load_from_directory_3_check_traverse_fn(c): + # test the actual traverse function... eventually this test can be + # removed, probably? + from sourmash import sourmash_args + + dirname = utils.get_test_data('prot') + files = list(sourmash_args.traverse_find_sigs([dirname])) + assert len(files) == 6, files + + files = list(sourmash_args.traverse_find_sigs([dirname], True)) + assert len(files) == 14, files + + +def test_multi_index_load_from_directory_no_exist(): + dirname = utils.get_test_data('does-not-exist') + with pytest.raises(ValueError): + mi = MultiIndex.load_from_directory(dirname, force=True) From 16a119e33cf83f33f8bfdab92af0aec37f00ee40 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 09:20:28 -0700 Subject: [PATCH 41/71] switch lca summarize over to usig MultiIndex --- src/sourmash/index.py | 18 +++++++++------- src/sourmash/lca/command_summarize.py | 22 +++++++------------- src/sourmash/sourmash_args.py | 6 +++--- tests/test_index.py | 30 +++++++++++++-------------- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index e6dd779b91..0d05a03726 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -195,6 +195,11 @@ def signatures(self): for ss in idx.signatures(): yield ss + def signatures_with_location(self): + for idx, loc in zip(self.index_list, self.source_list): + for ss in idx.signatures(): + yield ss, loc + def __len__(self): return sum([ len(idx) for idx in self.index_list ]) @@ -206,16 +211,15 @@ def load(self, *args): raise NotImplementedError @classmethod - def load_from_directory(cls, dirname, force=False): - "Create a MultiIndex from all files under a directory." + def load_from_path(cls, pathname, force=False): + "Create a MultiIndex from a path (filename or directory)." from .sourmash_args import traverse_find_sigs - if not os.path.isdir(dirname): - raise ValueError(f"'{dirname}' must be a directory") + if not os.path.exists(pathname): + raise ValueError(f"'{pathname}' must be a directory") index_list = [] source_list = [] - for thisfile in traverse_find_sigs([dirname], - yield_all_files=force): + for thisfile in traverse_find_sigs([pathname], yield_all_files=force): try: idx = LinearIndex.load(thisfile) index_list.append(idx) @@ -230,7 +234,7 @@ def load_from_directory(cls, dirname, force=False): if index_list: db = cls(index_list, source_list) else: - raise ValueError(f"no signatures to load under directory '{dirname}'") + raise ValueError(f"no signatures to load under directory '{pathname}'") return db diff --git a/src/sourmash/lca/command_summarize.py b/src/sourmash/lca/command_summarize.py index e64cca8e01..2d5ec5a375 100644 --- a/src/sourmash/lca/command_summarize.py +++ b/src/sourmash/lca/command_summarize.py @@ -10,6 +10,7 @@ from ..logging import notify, error, print_results, set_quiet, debug from . import lca_utils from .lca_utils import check_files_exist +from sourmash.index import MultiIndex DEFAULT_THRESHOLD=5 @@ -61,22 +62,15 @@ def load_singletons_and_count(filenames, ksize, scaled, ignore_abundance): total_count = 0 n = 0 - # in order to get the right reporting out of this function, we need - # to do our own traversal to expand the list of filenames, as opposed - # to using load_file_as_signatures(...) - filenames = sourmash_args.traverse_find_sigs(filenames) - filenames = list(filenames) - - # @CTB replace with MultiIndex? - total_n = len(filenames) - - for query_filename in filenames: + for filename in filenames: n += 1 - for query_sig in sourmash_args.load_file_as_signatures(query_filename, - ksize=ksize): + mi = MultiIndex.load_from_path(filename) + mi = mi.select(ksize=ksize) + + for query_sig, query_filename in mi.signatures_with_location(): notify(u'\r\033[K', end=u'') - notify('... loading {} (file {} of {})', query_sig, n, + notify(f'... loading {query_sig} (file {n} of {total_n})', total_n, end='\r') total_count += 1 @@ -89,7 +83,7 @@ def load_singletons_and_count(filenames, ksize, scaled, ignore_abundance): yield query_filename, query_sig, hashvals notify(u'\r\033[K', end=u'') - notify('loaded {} signatures from {} files total.', total_count, n) + notify(f'loaded {total_count} signatures from {n} files total.') def count_signature(sig, scaled, hashvals): diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 84a63c7bfa..3a1ee1dd6b 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -350,10 +350,10 @@ def _multiindex_load_from_file_list(filename, **kwargs): return (db, DatabaseType.SIGLIST) -def _multiindex_load_from_directory(filename, **kwargs): +def _multiindex_load_from_path(filename, **kwargs): "Load collection from a directory." traverse_yield_all = kwargs['traverse_yield_all'] - db = MultiIndex.load_from_directory(filename, traverse_yield_all) + db = MultiIndex.load_from_path(filename, traverse_yield_all) return (db, DatabaseType.SIGLIST) @@ -394,7 +394,7 @@ def _load_revindex(filename, **kwargs): # all loader functions, in order. _loader_functions = [ ("load from stdin", _load_stdin), - ("load from directory", _multiindex_load_from_directory), + ("load from directory", _multiindex_load_from_path), ("load from sig file", _load_sigfile), ("load from file list", _multiindex_load_from_file_list), ("load SBT", _load_sbt), diff --git a/tests/test_index.py b/tests/test_index.py index 6530243a8b..2b242e62c3 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -509,18 +509,18 @@ def test_multi_index_signatures(): assert ss63 in siglist -def test_multi_index_load_from_directory(): +def test_multi_index_load_from_path(): dirname = utils.get_test_data('prot/protein') - mi = MultiIndex.load_from_directory(dirname, force=False) + mi = MultiIndex.load_from_path(dirname, force=False) sigs = list(mi.signatures()) assert len(sigs) == 2 -def test_multi_index_load_from_directory_2(): +def test_multi_index_load_from_path_2(): # only load .sig files, currently; not the databases under that directory. dirname = utils.get_test_data('prot') - mi = MultiIndex.load_from_directory(dirname, force=False) + mi = MultiIndex.load_from_path(dirname, force=False) print(mi.index_list) print(mi.source_list) @@ -530,7 +530,7 @@ def test_multi_index_load_from_directory_2(): @utils.in_tempdir -def test_multi_index_load_from_directory_3(c): +def test_multi_index_load_from_path_3(c): # check that force works ok on a directory dirname = utils.get_test_data('prot') @@ -544,11 +544,11 @@ def test_multi_index_load_from_directory_3(c): count += 1 with pytest.raises(sourmash.exceptions.SourmashError): - mi = MultiIndex.load_from_directory(c.location, force=False) + mi = MultiIndex.load_from_path(c.location, force=False) @utils.in_tempdir -def test_multi_index_load_from_directory_3_yield_all_true(c): +def test_multi_index_load_from_path_3_yield_all_true(c): # check that force works ok on a directory w/force=True dirname = utils.get_test_data('prot') @@ -561,7 +561,7 @@ def test_multi_index_load_from_directory_3_yield_all_true(c): shutil.copyfile(fullname, copyto) count += 1 - mi = MultiIndex.load_from_directory(c.location, force=True) + mi = MultiIndex.load_from_path(c.location, force=True) print(mi.index_list) print(mi.source_list) @@ -571,7 +571,7 @@ def test_multi_index_load_from_directory_3_yield_all_true(c): @utils.in_tempdir -def test_multi_index_load_from_directory_3_yield_all_true_subdir(c): +def test_multi_index_load_from_path_3_yield_all_true_subdir(c): # check that force works ok on subdirectories dirname = utils.get_test_data('prot') @@ -587,7 +587,7 @@ def test_multi_index_load_from_directory_3_yield_all_true_subdir(c): shutil.copyfile(fullname, copyto) count += 1 - mi = MultiIndex.load_from_directory(c.location, force=True) + mi = MultiIndex.load_from_path(c.location, force=True) print(mi.index_list) print(mi.source_list) @@ -597,7 +597,7 @@ def test_multi_index_load_from_directory_3_yield_all_true_subdir(c): @utils.in_tempdir -def test_multi_index_load_from_directory_3_sig_gz(c): +def test_multi_index_load_from_path_3_sig_gz(c): # check that we find .sig.gz files, too dirname = utils.get_test_data('prot') @@ -612,7 +612,7 @@ def test_multi_index_load_from_directory_3_sig_gz(c): shutil.copyfile(fullname, copyto) count += 1 - mi = MultiIndex.load_from_directory(c.location, force=False) + mi = MultiIndex.load_from_path(c.location, force=False) print(mi.index_list) print(mi.source_list) @@ -622,7 +622,7 @@ def test_multi_index_load_from_directory_3_sig_gz(c): @utils.in_tempdir -def test_multi_index_load_from_directory_3_check_traverse_fn(c): +def test_multi_index_load_from_path_3_check_traverse_fn(c): # test the actual traverse function... eventually this test can be # removed, probably? from sourmash import sourmash_args @@ -635,7 +635,7 @@ def test_multi_index_load_from_directory_3_check_traverse_fn(c): assert len(files) == 14, files -def test_multi_index_load_from_directory_no_exist(): +def test_multi_index_load_from_path_no_exist(): dirname = utils.get_test_data('does-not-exist') with pytest.raises(ValueError): - mi = MultiIndex.load_from_directory(dirname, force=True) + mi = MultiIndex.load_from_path(dirname, force=True) From cb1e8a3c6c3e708d89501ef41aa3f6e0a75f842d Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 09:28:50 -0700 Subject: [PATCH 42/71] switch to using MultiIndex in categorize --- src/sourmash/commands.py | 22 ++++++++++++---------- tests/test_sourmash.py | 8 ++------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/sourmash/commands.py b/src/sourmash/commands.py index 35b88d0610..4584284829 100644 --- a/src/sourmash/commands.py +++ b/src/sourmash/commands.py @@ -519,6 +519,8 @@ def search(args): def categorize(args): "Use a database to find the best match to many signatures." + from .index import MultiIndex + set_quiet(args.quiet) moltype = sourmash_args.calculate_moltype(args) @@ -540,8 +542,13 @@ def categorize(args): notify('found {} files to query', len(inp_files)) - loader = sourmash_args.LoadSingleSignatures(inp_files, - args.ksize, moltype) + # utility function to load & select relevant signatures. + def _yield_all_sigs(queries, ksize, moltype): + for filename in queries: + mi = MultiIndex.load_from_path(filename, False) + mi = mi.select(ksize=ksize, moltype=moltype) + for ss, loc in mi.signatures_with_location(): + yield ss, loc csv_w = None csv_fp = None @@ -549,9 +556,9 @@ def categorize(args): csv_fp = open(args.csv, 'w', newline='') csv_w = csv.writer(csv_fp) - for queryfile, query, query_moltype, query_ksize in loader: + for query, loc in _yield_all_sigs(args.queries, args.ksize, moltype): notify('loaded query: {}... (k={}, {})', str(query)[:30], - query_ksize, query_moltype) + query.minhash.ksize, query.minhash.moltype) results = [] search_fn = SearchMinHashesFindBest().search @@ -576,14 +583,9 @@ def categorize(args): notify('for {}, no match found', query) if csv_w: - csv_w.writerow([queryfile, query, best_hit_query_name, + csv_w.writerow([loc, query, best_hit_query_name, best_hit_sim]) - if loader.skipped_ignore: - notify('skipped/ignore: {}', loader.skipped_ignore) - if loader.skipped_nosig: - notify('skipped/nosig: {}', loader.skipped_nosig) - if csv_fp: csv_fp.close() diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index 1a0d1d4d65..d690fd40ff 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -4238,8 +4238,7 @@ def test_sbt_categorize_already_done_traverse(): def test_sbt_categorize_multiple_ksizes_moltypes(): - # 'categorize' should fail when there are multiple ksizes or moltypes - # present + # 'categorize' works fine with multiple moltypes/ksizes with utils.TempDirectory() as location: testdata1 = utils.get_test_data('genome-s10.fa.gz.sig') testdata2 = utils.get_test_data('genome-s11.fa.gz.sig') @@ -4255,10 +4254,7 @@ def test_sbt_categorize_multiple_ksizes_moltypes(): args = ['categorize', 'zzz', '.'] status, out, err = utils.runscript('sourmash', args, - in_directory=location, fail_ok=True) - - assert status != 0 - assert 'multiple k-mer sizes/molecule types present' in err + in_directory=location) @utils.in_tempdir From c9e176d695a1e2ee7b5b0019289a3050dd15ce4c Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 09:30:04 -0700 Subject: [PATCH 43/71] remove LoadSingleSignatures --- src/sourmash/sourmash_args.py | 41 ----------------------------------- 1 file changed, 41 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 3a1ee1dd6b..c7b71774ea 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -111,47 +111,6 @@ def load_query_signature(filename, ksize, select_moltype, select_md5=None): return sl[0] -class LoadSingleSignatures(object): - def __init__(self, filelist, ksize=None, select_moltype=None, - ignore_files=set()): - self.filelist = filelist - self.ksize = ksize - self.select_moltype = select_moltype - self.ignore_files = ignore_files - - self.skipped_ignore = 0 - self.skipped_nosig = 0 - self.ksizes = set() - self.moltypes = set() - - def __iter__(self): - for filename in self.filelist: - if filename in self.ignore_files: - self.skipped_ignore += 1 - continue - - sl = signature.load_signatures(filename, - ksize=self.ksize, - select_moltype=self.select_moltype) - sl = list(sl) - if len(sl) == 0: - self.skipped_nosig += 1 - continue - - for query in sl: - query_moltype = get_moltype(query) - query_ksize = query.minhash.ksize - - self.ksizes.add(query_ksize) - self.moltypes.add(query_moltype) - - if len(self.ksizes) > 1 or len(self.moltypes) > 1: - raise ValueError('multiple k-mer sizes/molecule types present') - - for query in sl: - yield filename, query, query_moltype, query_ksize - - def _check_suffix(filename, endings): for ending in endings: if filename.endswith(ending): From 8f914f17fed37bcd4377ccf2d97e5b30b1a43de1 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 09:34:22 -0700 Subject: [PATCH 44/71] test errors in lca database loading --- tests/test_lca.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_lca.py b/tests/test_lca.py index b4c0c8e990..980c3655c3 100644 --- a/tests/test_lca.py +++ b/tests/test_lca.py @@ -394,6 +394,18 @@ def test_databases(): assert scaled == 10000 +def test_databases_load_fail_on_dir(): + filename1 = utils.get_test_data('lca') + with pytest.raises(ValueError) as exc: + dblist, ksize, scaled = lca_utils.load_databases([filename1]) + + +def test_databases_load_fail_on_not_exist(): + filename1 = utils.get_test_data('does-not-exist') + with pytest.raises(ValueError) as exc: + dblist, ksize, scaled = lca_utils.load_databases([filename1]) + + def test_db_repr(): filename = utils.get_test_data('lca/delmont-1.lca.json') db, ksize, scaled = lca_utils.load_single_database(filename) From a43b011bb211cd545841387165f611f0a60e5d12 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 10:07:54 -0700 Subject: [PATCH 45/71] remove unneeded categorize code --- src/sourmash/commands.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/sourmash/commands.py b/src/sourmash/commands.py index 4584284829..5f98a65fdd 100644 --- a/src/sourmash/commands.py +++ b/src/sourmash/commands.py @@ -535,13 +535,6 @@ def categorize(args): # load search database tree = load_sbt_index(args.sbt_name) - # load query filenames - # @CTB replace with MultiIndex? - inp_files = set(sourmash_args.traverse_find_sigs(args.queries)) - inp_files = inp_files - already_names - - notify('found {} files to query', len(inp_files)) - # utility function to load & select relevant signatures. def _yield_all_sigs(queries, ksize, moltype): for filename in queries: @@ -557,6 +550,10 @@ def _yield_all_sigs(queries, ksize, moltype): csv_w = csv.writer(csv_fp) for query, loc in _yield_all_sigs(args.queries, args.ksize, moltype): + # skip if we've already done signatures from this file. + if loc in already_names: + continue + notify('loaded query: {}... (k={}, {})', str(query)[:30], query.minhash.ksize, query.minhash.moltype) From 15328aec469e1e2a88a036fe4ba7879c6298776e Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 10:12:00 -0700 Subject: [PATCH 46/71] add testme info --- src/sourmash/sourmash_args.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index c7b71774ea..e8aa1eff66 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -220,8 +220,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) try: db, dbtype = _load_database(filename, False, cache_size=cache_size) except IOError as e: - raise - notify(str(e)) + notify(str(e)) # @CTB test me sys.exit(-1) # are we collecting signatures from an SBT? @@ -304,7 +303,7 @@ def _multiindex_load_from_file_list(filename, **kwargs): try: db = MultiIndex.load_from_file_list(filename) except UnicodeDecodeError as exc: - raise ValueError(exc) + raise ValueError(exc) # @CTB test me return (db, DatabaseType.SIGLIST) @@ -323,7 +322,7 @@ def _load_sigfile(filename, **kwargs): db = LinearIndex.load(filename) except sourmash.exceptions.SourmashError as exc: raise ValueError(exc) - except FileNotFoundError: + except FileNotFoundError: # @CTB test me raise ValueError(f"Error while reading signatures from '{filename}'") return (db, DatabaseType.SIGLIST) @@ -343,10 +342,7 @@ def _load_sbt(filename, **kwargs): def _load_revindex(filename, **kwargs): "Load collection from an LCA database/reverse index." - try: - db, _, _ = load_single_database(filename) - except FileNotFoundError as exc: - raise ValueError(exc) + db, _, _ = load_single_database(filename) return (db, DatabaseType.LCA) @@ -393,7 +389,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): successful_screed_load = False it = None try: - # CTB: could be kind of time consuming for big record, but at the + # CTB: could be kind of time consuming for a big record, but at the # moment screed doesn't expose format detection cleanly. with screed.open(filename) as it: record = next(iter(it)) From f674232a57aab40263a01a137829e7564eca95d5 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 12:16:53 -0700 Subject: [PATCH 47/71] verified that this was tested --- src/sourmash/sourmash_args.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index e8aa1eff66..f23b318a12 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -219,8 +219,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) try: db, dbtype = _load_database(filename, False, cache_size=cache_size) - except IOError as e: - notify(str(e)) # @CTB test me + except Exception as e: + notify(str(e)) sys.exit(-1) # are we collecting signatures from an SBT? From 01c54c0fe3a737694586d90de18cc311a3921769 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 12:22:23 -0700 Subject: [PATCH 48/71] remove testme comments --- src/sourmash/sourmash_args.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index f23b318a12..58bf3ff3af 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -300,10 +300,7 @@ def _load_stdin(filename, **kwargs): def _multiindex_load_from_file_list(filename, **kwargs): "Load collection from a list of signature/database files" - try: - db = MultiIndex.load_from_file_list(filename) - except UnicodeDecodeError as exc: - raise ValueError(exc) # @CTB test me + db = MultiIndex.load_from_file_list(filename) return (db, DatabaseType.SIGLIST) @@ -322,8 +319,6 @@ def _load_sigfile(filename, **kwargs): db = LinearIndex.load(filename) except sourmash.exceptions.SourmashError as exc: raise ValueError(exc) - except FileNotFoundError: # @CTB test me - raise ValueError(f"Error while reading signatures from '{filename}'") return (db, DatabaseType.SIGLIST) From ae3f66de1c42c0578eaecfa370ceb8ce021e87b1 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 12:29:23 -0700 Subject: [PATCH 49/71] add tests for MultiIndex.load_from_file_list --- tests/test_index.py | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/tests/test_index.py b/tests/test_index.py index 2b242e62c3..f26cc3fc0a 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -11,6 +11,7 @@ from sourmash import load_one_signature, SourmashSignature from sourmash.index import LinearIndex, MultiIndex from sourmash.sbt import SBT, GraphFactory, Leaf +from sourmash import sourmash_args import sourmash_tst_utils as utils @@ -624,9 +625,8 @@ def test_multi_index_load_from_path_3_sig_gz(c): @utils.in_tempdir def test_multi_index_load_from_path_3_check_traverse_fn(c): # test the actual traverse function... eventually this test can be - # removed, probably? - from sourmash import sourmash_args - + # removed, probably, as we consolidate functionality and test MultiIndex + # better. dirname = utils.get_test_data('prot') files = list(sourmash_args.traverse_find_sigs([dirname])) assert len(files) == 6, files @@ -639,3 +639,40 @@ def test_multi_index_load_from_path_no_exist(): dirname = utils.get_test_data('does-not-exist') with pytest.raises(ValueError): mi = MultiIndex.load_from_path(dirname, force=True) + + +def test_multi_index_load_from_file_list_no_exist(): + dirname = utils.get_test_data('does-not-exist') + with pytest.raises(ValueError): + mi = MultiIndex.load_from_file_list(dirname) + + +@utils.in_tempdir +def test_multi_index_load_from_file_list_1(c): + dirname = utils.get_test_data('prot') + files = list(sourmash_args.traverse_find_sigs([dirname])) + assert len(files) == 6, files + + file_list = c.output('filelist.txt') + + with open(file_list, 'wt') as fp: + print("\n".join(files), file=fp) + mi = MultiIndex.load_from_file_list(file_list) + + sigs = list(mi.signatures()) + assert len(sigs) == 6 + + +@utils.in_tempdir +def test_multi_index_load_from_file_list_2(c): + dirname = utils.get_test_data('prot') + files = list(sourmash_args.traverse_find_sigs([dirname], True)) + assert len(files) == 14, files + + file_list = c.output('filelist.txt') + + with open(file_list, 'wt') as fp: + print("\n".join(files), file=fp) + + with pytest.raises(ValueError): + mi = MultiIndex.load_from_file_list(file_list) From 7f52d7cc6dcae814ea1ba2130ad4a4fc78a196ff Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 14:23:21 -0700 Subject: [PATCH 50/71] refactor select, add scaled/num/abund --- src/sourmash/index.py | 28 ++++++++++----- src/sourmash/sourmash_args.py | 65 ++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 0d05a03726..1a04e3b9f3 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -124,7 +124,8 @@ def gather(self, query, *args, **kwargs): return results @abstractmethod - def select(self, ksize=None, moltype=None): + def select(self, ksize=None, moltype=None, scaled=None, num=None, + abund=None): "" class LinearIndex(Index): @@ -157,11 +158,22 @@ def load(cls, location): lidx = LinearIndex(si, filename=location) return lidx - def select(self, ksize=None, moltype=None): - def select_sigs(ss, ksize=ksize, moltype=moltype): - if (ksize is None or ss.minhash.ksize == ksize) and \ - (moltype is None or ss.minhash.moltype == moltype): - return True + def select(self, **kwargs): + def select_sigs(ss): + # eliminate things from kwargs with no value + kw = { k : v for (k, v) in kwargs.items() if v is not None } + if 'ksize' in kw and kw['ksize'] != ss.minhash.ksize: + return False + if 'moltype' in kw and kw['moltype'] != ss.minhash.moltype: + return False + if 'scaled' in kw: + if ss.minhash.num or kw['scaled'] != ss.minhash.scaled: + return False + if 'num' in kw: + if ss.minhash.scaled or kw['num'] != ss.minhash.num: + return False + + return True return self.filter(select_sigs) @@ -260,11 +272,11 @@ def load_from_file_list(cls, filename): def save(self, *args): raise NotImplementedError - def select(self, ksize=None, moltype=None): + def select(self, **kwargs): new_idx_list = [] new_src_list = [] for idx, src in zip(self.index_list, self.source_list): - idx = idx.select(ksize=ksize, moltype=moltype) + idx = idx.select(**kwargs) new_idx_list.append(idx) new_src_list.append(src) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 58bf3ff3af..23901e9ca2 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -223,45 +223,48 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(str(e)) sys.exit(-1) - # are we collecting signatures from an SBT? - if dbtype == DatabaseType.SBT: - if not check_tree_is_compatible(filename, db, query, - is_similarity_query): - sys.exit(-1) + #db = db.select(moltype=query_moltype, ksize=query_ksize) + #databases.append(db) + + if 1: + # are we collecting signatures from an SBT? + if dbtype == DatabaseType.SBT: + if not check_tree_is_compatible(filename, db, query, + is_similarity_query): + sys.exit(-1) - databases.append(db) - notify(f'loaded SBT {filename}', end='\r') - n_databases += 1 + databases.append(db) + notify(f'loaded SBT {filename}', end='\r') + n_databases += 1 - # or an LCA? - elif dbtype == DatabaseType.LCA: - if not check_lca_db_is_compatible(filename, db, query): - sys.exit(-1) + # or an LCA? + elif dbtype == DatabaseType.LCA: + if not check_lca_db_is_compatible(filename, db, query): + sys.exit(-1) - notify(f'loaded LCA {filename}', end='\r') - n_databases += 1 + notify(f'loaded LCA {filename}', end='\r') + n_databases += 1 - databases.append(db) + databases.append(db) - # or a mixed collection of signatures? - elif dbtype == DatabaseType.SIGLIST: - db = db.select(moltype=query_moltype, ksize=query_ksize) - siglist = db.signatures() - filter_fn = lambda s: _check_signatures_are_compatible(query, s) - db = db.filter(filter_fn) + # or a mixed collection of signatures? + elif dbtype == DatabaseType.SIGLIST: + db = db.select(moltype=query_moltype, ksize=query_ksize) + filter_fn = lambda s: _check_signatures_are_compatible(query, s) + db = db.filter(filter_fn) - if not db: - notify(f"no compatible signatures found in '{filename}'") - sys.exit(-1) + if not db: + notify(f"no compatible signatures found in '{filename}'") + sys.exit(-1) - databases.append(db) + databases.append(db) - notify(f'loaded {len(db)} signatures from {filename}', end='\r') - n_signatures += len(db) + notify(f'loaded {len(db)} signatures from {filename}', end='\r') + n_signatures += len(db) - # unknown!? - else: - raise ValueError(f"unknown dbtype {dbtype}") # CTB check me. + # unknown!? + else: + raise ValueError(f"unknown dbtype {dbtype}") # CTB check me. # END for loop @@ -273,7 +276,7 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(f'loaded {n_signatures} signatures.') elif n_databases: notify(f'loaded {n_databases} databases.') - else: + elif 0: notify('** ERROR: no signatures or databases loaded?') sys.exit(-1) From dde14fd3e476217c0836d5b05543516a02a6785a Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 14:34:42 -0700 Subject: [PATCH 51/71] more work --- src/sourmash/index.py | 8 ++++++-- src/sourmash/lca/lca_db.py | 8 +++++++- src/sourmash/sbt.py | 7 ++++++- src/sourmash/sourmash_args.py | 13 +++++++++---- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 1a04e3b9f3..7158095803 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -160,8 +160,12 @@ def load(cls, location): def select(self, **kwargs): def select_sigs(ss): - # eliminate things from kwargs with no value - kw = { k : v for (k, v) in kwargs.items() if v is not None } + # eliminate things from kwargs with no or zero + kw = { k : v for (k, v) in kwargs.items() if v } + print(kw, kwargs) + if not kw: + return True + if 'ksize' in kw and kw['ksize'] != ss.minhash.ksize: return False if 'moltype' in kw and kw['moltype'] != ss.minhash.moltype: diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index 137f0fbd5c..a290db345e 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -169,8 +169,14 @@ def signatures(self): for v in self._signatures.values(): yield v - def select(self, ksize=None, moltype=None): + def select(self, ksize=None, moltype=None, num=0, scaled=0): "Selector interface - make sure this database matches requirements." + if num: + raise ValueError("cannot use num MinHashes on LCA database") + + if scaled < self.scaled: + raise ValueError(f"cannot use scaled={scaled} on this database ({self.scaled})") + ok = True if ksize is not None and self.ksize != ksize: ok = False diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index c499f50e2c..051c5c7fc5 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -189,7 +189,7 @@ def signatures(self): for k in self.leaves(): yield k.data - def select(self, ksize=None, moltype=None): + def select(self, ksize=None, moltype=None, num=0, scaled=0): first_sig = next(iter(self.signatures())) ok = True @@ -198,6 +198,11 @@ def select(self, ksize=None, moltype=None): if moltype is not None and first_sig.minhash.moltype != moltype: ok = False + if num and not (num and first_sig.minhash.num): + raise ValueError(f"cannot search SBT: num={num}, {first_sig.minhash.num}") + if scaled and not (scaled and first_sig.minhash.scaled): + raise ValueError(f"cannot search SBT: scaled={scaled}, {first_sig.minhash.scaled}") + if ok: return self diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 23901e9ca2..084008f0cc 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -223,10 +223,13 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(str(e)) sys.exit(-1) - #db = db.select(moltype=query_moltype, ksize=query_ksize) - #databases.append(db) + db = db.select(moltype=query_moltype, + ksize=query_ksize, + num=query.minhash.num, + scaled=query.minhash.scaled) + databases.append(db) - if 1: + if 0: # are we collecting signatures from an SBT? if dbtype == DatabaseType.SBT: if not check_tree_is_compatible(filename, db, query, @@ -276,7 +279,9 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(f'loaded {n_signatures} signatures.') elif n_databases: notify(f'loaded {n_databases} databases.') - elif 0: + + + if not databases: notify('** ERROR: no signatures or databases loaded?') sys.exit(-1) From 3f498a4fea278b9e643cdb6c5d3d9364e86798c1 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Sun, 28 Mar 2021 17:28:38 -0700 Subject: [PATCH 52/71] catch ValueError from db.select --- src/sourmash/sourmash_args.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 084008f0cc..df5e25a08c 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -223,11 +223,15 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(str(e)) sys.exit(-1) - db = db.select(moltype=query_moltype, - ksize=query_ksize, - num=query.minhash.num, - scaled=query.minhash.scaled) - databases.append(db) + try: + db = db.select(moltype=query_moltype, + ksize=query_ksize, + num=query.minhash.num, + scaled=query.minhash.scaled) + databases.append(db) + except ValueError: + notify(f"cannot use {filename} for this query") + continue if 0: # are we collecting signatures from an SBT? From df199265de4e555563cf96b8265b42651596d1db Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 29 Mar 2021 07:24:09 -0700 Subject: [PATCH 53/71] update debug print to sys.stder --- src/sourmash/index.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 7158095803..1562b57c60 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -162,7 +162,8 @@ def select(self, **kwargs): def select_sigs(ss): # eliminate things from kwargs with no or zero kw = { k : v for (k, v) in kwargs.items() if v } - print(kw, kwargs) + import sys + print(kw, kwargs, file=sys.stderr) if not kw: return True From e8233caa73e3a7af6324fe3e6b90da2b629eb3cd Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 29 Mar 2021 07:24:36 -0700 Subject: [PATCH 54/71] fix scaled check for LCA database --- src/sourmash/lca/lca_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index a290db345e..85ca86099a 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -174,7 +174,7 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0): if num: raise ValueError("cannot use num MinHashes on LCA database") - if scaled < self.scaled: + if scaled > self.scaled: raise ValueError(f"cannot use scaled={scaled} on this database ({self.scaled})") ok = True From b44c3cf6da3f8b047aee7d197406ef2bdc69e73f Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 29 Mar 2021 07:24:45 -0700 Subject: [PATCH 55/71] add debug_literal --- src/sourmash/logging.py | 11 +++++++++++ src/sourmash/sourmash_args.py | 8 ++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/sourmash/logging.py b/src/sourmash/logging.py index 49c3dc26b3..2915c43f78 100644 --- a/src/sourmash/logging.py +++ b/src/sourmash/logging.py @@ -41,6 +41,17 @@ def debug(s, *args, **kwargs): sys.stderr.flush() +def debug_literal(s, *args, **kwargs): + "A debug logging function => stderr." + if _quiet or not _debug: + return + + print(u'\r\033[K', end=u'', file=sys.stderr) + print(s, file=sys.stderr, end=kwargs.get('end', u'\n')) + if kwargs.get('flush'): + sys.stderr.flush() + + def error(s, *args, **kwargs): "A simple error logging function => stderr." print(u'\r\033[K', end=u'', file=sys.stderr) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index df5e25a08c..7fc36a8888 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -15,7 +15,7 @@ import sourmash.exceptions from . import signature -from .logging import notify, error, debug +from .logging import notify, error, debug_literal from .index import LinearIndex, MultiIndex from . import signature as sig @@ -378,13 +378,13 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): # but nothing else. for (desc, load_fn) in _loader_functions: try: - debug(f"_load_databases: trying loader fn {desc}") + debug_literal(f"_load_databases: trying loader fn {desc}") db, dbtype = load_fn(filename, traverse_yield_all=traverse_yield_all, cache_size=cache_size) except ValueError as exc: - debug(f"_load_databases: FAIL on fn {desc}.") - debug(traceback.format_exc()) + debug_literal(f"_load_databases: FAIL on fn {desc}.") + debug_literal(traceback.format_exc()) if db: loaded = True From 7133ac118226c51b0e18b275b18f4877b7e2f9af Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 29 Mar 2021 07:36:32 -0700 Subject: [PATCH 56/71] break things when filter returns empty Index --- src/sourmash/index.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 1562b57c60..a8a1f2f97a 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -188,6 +188,9 @@ def filter(self, filter_fn): if filter_fn(ss): siglist.append(ss) + if not siglist: + raise ValueError("no signatures match") + return LinearIndex(siglist, self.filename) From f5f1c9c8c472c0398390fc409b6674a635f92f10 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 29 Mar 2021 07:43:56 -0700 Subject: [PATCH 57/71] fix scaled check for SBT --- src/sourmash/sbt.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 051c5c7fc5..579be0e48f 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -198,10 +198,17 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0): if moltype is not None and first_sig.minhash.moltype != moltype: ok = False - if num and not (num and first_sig.minhash.num): - raise ValueError(f"cannot search SBT: num={num}, {first_sig.minhash.num}") - if scaled and not (scaled and first_sig.minhash.scaled): - raise ValueError(f"cannot search SBT: scaled={scaled}, {first_sig.minhash.scaled}") + if num: + if not (num and first_sig.minhash.num): + raise ValueError(f"cannot search SBT: num={num}, {first_sig.minhash.num}") + if num == first_sig.minhash.num: + raise ValueError(f"num mismatch for SBT: num={num}, {first_sig.minhash.num}") + + if scaled: + if not (scaled and first_sig.minhash.scaled): + raise ValueError(f"cannot search SBT: scaled={scaled}, {first_sig.minhash.scaled}") + if scaled > first_sig.minhash.scaled: + raise ValueError(f"scaled mismatch: {scaled}, {first_sig.minhash.scaled}") if ok: return self From d6f156f91a7d86c1e884d15d5f69cd3f26900700 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Mon, 29 Mar 2021 17:24:00 -0700 Subject: [PATCH 58/71] fix a few tests --- src/sourmash/index.py | 3 --- src/sourmash/sbt.py | 2 +- src/sourmash/sourmash_args.py | 8 +++++++- tests/test_sourmash.py | 10 ++++------ 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index a8a1f2f97a..1562b57c60 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -188,9 +188,6 @@ def filter(self, filter_fn): if filter_fn(ss): siglist.append(ss) - if not siglist: - raise ValueError("no signatures match") - return LinearIndex(siglist, self.filename) diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 579be0e48f..53ce710eed 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -201,7 +201,7 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0): if num: if not (num and first_sig.minhash.num): raise ValueError(f"cannot search SBT: num={num}, {first_sig.minhash.num}") - if num == first_sig.minhash.num: + if num != first_sig.minhash.num: raise ValueError(f"num mismatch for SBT: num={num}, {first_sig.minhash.num}") if scaled: diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 7fc36a8888..2396f1b03e 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -228,11 +228,17 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) ksize=query_ksize, num=query.minhash.num, scaled=query.minhash.scaled) - databases.append(db) except ValueError: + raise notify(f"cannot use {filename} for this query") continue + if not db: + notify(f"no compatible signatures found in '{filename}'") + sys.exit(-1) + + databases.append(db) + if 0: # are we collecting signatures from an SBT? if dbtype == DatabaseType.SBT: diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index d690fd40ff..21ba999ad0 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -1857,6 +1857,8 @@ def test_search_incompatible(c): @utils.in_tempdir def test_search_traverse_incompatible(c): + # build a directory with some signatures in it, search for compatible + # signatures. searchdir = c.output('searchme') os.mkdir(searchdir) @@ -1866,10 +1868,7 @@ def test_search_traverse_incompatible(c): shutil.copyfile(scaled_sig, c.output('searchme/scaled.sig')) c.run_sourmash("search", scaled_sig, c.output('searchme')) - print(c.last_result.out) - print(c.last_result.err) - assert 'incompatible - cannot compare.' in c.last_result.err - assert 'was calculated with --scaled,' in c.last_result.err + assert '100.0% NC_009665.1 Shewanella baltica OS185, complete genome' in c.last_result.out # explanation: you cannot downsample a scaled SBT to match a scaled @@ -3604,8 +3603,7 @@ def test_gather_traverse_incompatible(c): c.run_sourmash("gather", scaled_sig, c.output('searchme')) print(c.last_result.out) print(c.last_result.err) - assert 'incompatible - cannot compare.' in c.last_result.err - assert 'was calculated with --scaled,' in c.last_result.err + assert "5.2 Mbp 100.0% 100.0% NC_009665.1 Shewanella baltica OS185,..." in c.last_result.out def test_gather_metagenome_output_unassigned(): From 785a9a40e36f12657434d660d3deb1090e4c8130 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Tue, 30 Mar 2021 06:20:24 -0700 Subject: [PATCH 59/71] fix LCA database ksize message & test --- src/sourmash/lca/lca_db.py | 10 +++------- src/sourmash/sourmash_args.py | 8 ++++---- tests/test_lca.py | 4 ++-- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index 85ca86099a..5c2b91524f 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -177,16 +177,12 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0): if scaled > self.scaled: raise ValueError(f"cannot use scaled={scaled} on this database ({self.scaled})") - ok = True if ksize is not None and self.ksize != ksize: - ok = False + raise ValueError(f"ksize on this database is {self.ksize}; this is different from requested ksize of {ksize}") if moltype is not None and moltype != self.moltype: - ok = False + raise ValueError(f"moltype on this database is {self.moltype}; this is different from requested moltype of {moltype}") - if ok: - return self - - raise ValueError("cannot select LCA on ksize {} / moltype {}".format(ksize, moltype)) + return self @classmethod def load(cls, db_name): diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 2396f1b03e..20a2841082 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -228,10 +228,10 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) ksize=query_ksize, num=query.minhash.num, scaled=query.minhash.scaled) - except ValueError: - raise - notify(f"cannot use {filename} for this query") - continue + except ValueError as exc: + notify(f"ERROR: cannot use '{filename}' for this query.") + notify(str(exc)) + sys.exit(-1) if not db: notify(f"no compatible signatures found in '{filename}'") diff --git a/tests/test_lca.py b/tests/test_lca.py index 980c3655c3..65fec92350 100644 --- a/tests/test_lca.py +++ b/tests/test_lca.py @@ -1908,8 +1908,8 @@ def test_incompat_lca_db_ksize_2(c): err = c.last_result.err print(err) - assert "ksize on db 'test.lca.json' is 25;" in err - assert 'this is different from query ksize of 31.' in err + assert "ERROR: cannot use 'test.lca.json' for this query." in err + assert "ksize on this database is 25; this is different from requested ksize of 31" @utils.in_tempdir From 23d7ac42b5b01bb954f675400dd81796d7b66730 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Tue, 30 Mar 2021 06:22:25 -0700 Subject: [PATCH 60/71] flag for removal --- src/sourmash/index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 1562b57c60..e2e4a8f698 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -162,8 +162,8 @@ def select(self, **kwargs): def select_sigs(ss): # eliminate things from kwargs with no or zero kw = { k : v for (k, v) in kwargs.items() if v } - import sys - print(kw, kwargs, file=sys.stderr) + #import sys # @CTB remove + #print(kw, kwargs, file=sys.stderr) if not kw: return True From 12399e78e490defc4f21a6bdd9109685343cbcba Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 07:06:00 -0700 Subject: [PATCH 61/71] add 'containment' to 'select' --- src/sourmash/index.py | 9 ++++++++- src/sourmash/lca/lca_db.py | 5 +++-- src/sourmash/sbt.py | 11 +++++++++-- src/sourmash/sourmash_args.py | 7 ++++++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index e2e4a8f698..16b05e0867 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -125,7 +125,7 @@ def gather(self, query, *args, **kwargs): @abstractmethod def select(self, ksize=None, moltype=None, scaled=None, num=None, - abund=None): + abund=None, containment=None): "" class LinearIndex(Index): @@ -171,6 +171,13 @@ def select_sigs(ss): return False if 'moltype' in kw and kw['moltype'] != ss.minhash.moltype: return False + + if 'containment' in kw: + if not 'scaled' in kw: + raise ValueError("'containment' requires 'scaled' in Index.select'") + if not ss.minhash.scaled: + return False + if 'scaled' in kw: if ss.minhash.num or kw['scaled'] != ss.minhash.scaled: return False diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index 5c2b91524f..1dcacdfdcd 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -169,12 +169,13 @@ def signatures(self): for v in self._signatures.values(): yield v - def select(self, ksize=None, moltype=None, num=0, scaled=0): + def select(self, ksize=None, moltype=None, num=0, scaled=0, + containment=False): "Selector interface - make sure this database matches requirements." if num: raise ValueError("cannot use num MinHashes on LCA database") - if scaled > self.scaled: + if scaled > self.scaled and not containment: raise ValueError(f"cannot use scaled={scaled} on this database ({self.scaled})") if ksize is not None and self.ksize != ksize: diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 53ce710eed..866d50c215 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -189,7 +189,8 @@ def signatures(self): for k in self.leaves(): yield k.data - def select(self, ksize=None, moltype=None, num=0, scaled=0): + def select(self, ksize=None, moltype=None, num=0, scaled=0, + containment=False): first_sig = next(iter(self.signatures())) ok = True @@ -198,6 +199,12 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0): if moltype is not None and first_sig.minhash.moltype != moltype: ok = False + if containment: + if not scaled: + raise ValueError("'containment' requires 'scaled' in SBT.select'") + if not first_sig.minhash.scaled: + raise ValueError("cannot search this SBT for containment; signatures are not calculated with scaled") + if num: if not (num and first_sig.minhash.num): raise ValueError(f"cannot search SBT: num={num}, {first_sig.minhash.num}") @@ -207,7 +214,7 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0): if scaled: if not (scaled and first_sig.minhash.scaled): raise ValueError(f"cannot search SBT: scaled={scaled}, {first_sig.minhash.scaled}") - if scaled > first_sig.minhash.scaled: + if scaled > first_sig.minhash.scaled and not containment: raise ValueError(f"scaled mismatch: {scaled}, {first_sig.minhash.scaled}") if ok: diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 20a2841082..e9661cf3b3 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -211,6 +211,10 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) query_ksize = query.minhash.ksize query_moltype = get_moltype(query) + containment = True + if is_similarity_query: + containment = False + n_signatures = 0 n_databases = 0 databases = [] @@ -227,7 +231,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) db = db.select(moltype=query_moltype, ksize=query_ksize, num=query.minhash.num, - scaled=query.minhash.scaled) + scaled=query.minhash.scaled, + containment=containment) except ValueError as exc: notify(f"ERROR: cannot use '{filename}' for this query.") notify(str(exc)) From 2b7acb9ce821558f8e3476fabeaf1239be01f894 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 07:45:34 -0700 Subject: [PATCH 62/71] fix remaining tests --- src/sourmash/index.py | 2 +- src/sourmash/sbt.py | 33 +++++++++++++++----------------- tests/test_sourmash.py | 43 +++++++++++++++++++++++++++++++----------- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 16b05e0867..94d6295478 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -179,7 +179,7 @@ def select_sigs(ss): return False if 'scaled' in kw: - if ss.minhash.num or kw['scaled'] != ss.minhash.scaled: + if ss.minhash.num: return False if 'num' in kw: if ss.minhash.scaled or kw['num'] != ss.minhash.num: diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 866d50c215..74ef736f32 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -192,35 +192,32 @@ def signatures(self): def select(self, ksize=None, moltype=None, num=0, scaled=0, containment=False): first_sig = next(iter(self.signatures())) + db_mh = first_sig.minhash - ok = True - if ksize is not None and first_sig.minhash.ksize != ksize: - ok = False - if moltype is not None and first_sig.minhash.moltype != moltype: - ok = False + if ksize is not None and db_mh.ksize != ksize: + raise ValueError(f"search ksize {ksize} is different from database ksize {db_mh.ksize}") + if moltype is not None and db_mh.moltype != moltype: + raise ValueError(f"search moltype {moltype} is different from database moltype {db_mh.moltype}") if containment: if not scaled: raise ValueError("'containment' requires 'scaled' in SBT.select'") - if not first_sig.minhash.scaled: + if not db_mh.scaled: raise ValueError("cannot search this SBT for containment; signatures are not calculated with scaled") if num: - if not (num and first_sig.minhash.num): - raise ValueError(f"cannot search SBT: num={num}, {first_sig.minhash.num}") - if num != first_sig.minhash.num: - raise ValueError(f"num mismatch for SBT: num={num}, {first_sig.minhash.num}") + if not db_mh.num: + raise ValueError(f"this database was created with 'scaled' MinHash sketches, not 'num'") + if num != db_mh.num: + raise ValueError(f"num mismatch for SBT: num={num}, {db_mh.num}") if scaled: - if not (scaled and first_sig.minhash.scaled): - raise ValueError(f"cannot search SBT: scaled={scaled}, {first_sig.minhash.scaled}") - if scaled > first_sig.minhash.scaled and not containment: - raise ValueError(f"scaled mismatch: {scaled}, {first_sig.minhash.scaled}") + if not db_mh.scaled: + raise ValueError(f"this database was created with 'num' MinHash sketches, not 'scaled'") + if scaled > db_mh.scaled and not containment: + raise ValueError(f"search scaled value {scaled} is less than database scaled value of {db_mh.scaled}") - if ok: - return self - - raise ValueError("cannot select SBT on ksize {} / moltype {}".format(ksize, moltype)) + return self def new_node_pos(self, node): if not self._nodes: diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index 21ba999ad0..ca520e05ad 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -1851,8 +1851,8 @@ def test_search_incompatible(c): assert c.last_result.status != 0 print(c.last_result.out) print(c.last_result.err) - assert 'incompatible - cannot compare.' in c.last_result.err - assert 'was calculated with --scaled,' in c.last_result.err + + assert "no compatible signatures found in " in c.last_result.err @utils.in_tempdir @@ -1895,8 +1895,11 @@ def test_search_metagenome_downsample(): in_directory=location, fail_ok=True) assert status == -1 - assert "for tree 'gcf_all', scaled value is smaller than query." in err - assert 'tree scaled: 10000; query scaled: 100000. Cannot do similarity search.' in err + print(out) + print(err) + + assert "ERROR: cannot use 'gcf_all' for this query." in err + assert "search scaled value 100000 is less than database scaled value of 10000" in err def test_search_metagenome_downsample_containment(): @@ -2054,7 +2057,11 @@ def test_do_sourmash_sbt_search_wrong_ksize(): fail_ok=True) assert status == -1 - assert 'this is different from' in err + print(out) + print(err) + + assert "ERROR: cannot use 'zzz' for this query." in err + assert "search ksize 51 is different from database ksize 31" in err def test_do_sourmash_sbt_search_multiple(): @@ -2169,7 +2176,10 @@ def test_do_sourmash_sbt_search_downsample_2(): '--threshold=0.01'], in_directory=location, fail_ok=True) assert status == -1 - assert 'Cannot do similarity search.' in err + print(out) + print(err) + assert "ERROR: cannot use 'foo' for this query." in err + assert "search scaled value 100000 is less than database scaled value of 2000" in err def test_do_sourmash_index_single(): @@ -2464,7 +2474,10 @@ def test_do_sourmash_sbt_search_scaled_vs_num_1(): fail_ok=True) assert status == -1 - assert 'tree and query are incompatible for search' in err + print(out) + print(err) + assert "ERROR: cannot use '" in err + assert "this database was created with 'num' MinHash sketches, not 'scaled'" in err def test_do_sourmash_sbt_search_scaled_vs_num_2(): @@ -2496,7 +2509,10 @@ def test_do_sourmash_sbt_search_scaled_vs_num_2(): fail_ok=True) assert status == -1 - assert 'tree and query are incompatible for search' in err + print(out) + print(err) + assert "ERROR: cannot use '" in err + assert "this database was created with 'scaled' MinHash sketches, not 'num'" in err def test_do_sourmash_sbt_search_scaled_vs_num_3(): @@ -2521,7 +2537,9 @@ def test_do_sourmash_sbt_search_scaled_vs_num_3(): fail_ok=True) assert status == -1 - assert 'incompatible - cannot compare' in err + print(out) + print(err) + assert "no compatible signatures found in " in err def test_do_sourmash_sbt_search_scaled_vs_num_4(): @@ -2546,7 +2564,9 @@ def test_do_sourmash_sbt_search_scaled_vs_num_4(): ['search', sig_loc2, sig_loc], fail_ok=True) assert status == -1 - assert 'incompatible - cannot compare' in err + print(out) + print(err) + assert "no compatible signatures found in " in err def test_do_sourmash_check_search_vs_actual_similarity(): @@ -3748,6 +3768,7 @@ def test_gather_query_downsample(): with utils.TempDirectory() as location: testdata_glob = utils.get_test_data('gather/GCF*.sig') testdata_sigs = glob.glob(testdata_glob) + print(testdata_sigs) query_sig = utils.get_test_data('GCF_000006945.2-s500.sig') @@ -3759,7 +3780,7 @@ def test_gather_query_downsample(): print(out) print(err) - assert 'loaded 12 signatures' in err + # assert 'loaded 12 signatures' in err @CTB assert all(('4.9 Mbp 100.0% 100.0%' in out, 'NC_003197.2' in out)) From 9aae1cb761305028bca89085f31f0c9e08f7fe16 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 07:53:45 -0700 Subject: [PATCH 63/71] update comments --- src/sourmash/index.py | 14 +++++++++++--- src/sourmash/lca/lca_db.py | 4 ++-- src/sourmash/sbt.py | 9 +++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 94d6295478..dcfa340ccb 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -162,26 +162,33 @@ def select(self, **kwargs): def select_sigs(ss): # eliminate things from kwargs with no or zero kw = { k : v for (k, v) in kwargs.items() if v } - #import sys # @CTB remove - #print(kw, kwargs, file=sys.stderr) + + # nothing to select on? we're all good. if not kw: return True + # ksize match? if 'ksize' in kw and kw['ksize'] != ss.minhash.ksize: return False + + # moltype match? if 'moltype' in kw and kw['moltype'] != ss.minhash.moltype: return False + # containment requires scaled; similarity does not. if 'containment' in kw: if not 'scaled' in kw: raise ValueError("'containment' requires 'scaled' in Index.select'") if not ss.minhash.scaled: return False + # 'scaled' and 'num' are incompatible if 'scaled' in kw: if ss.minhash.num: return False if 'num' in kw: + # note, here we check if 'num' is identical; this can be + # changed later. if ss.minhash.scaled or kw['num'] != ss.minhash.num: return False @@ -189,7 +196,7 @@ def select_sigs(ss): return self.filter(select_sigs) - def filter(self, filter_fn): + def filter(self, filter_fn): # @CTB may not be necessary any more siglist = [] for ss in self._signatures: if filter_fn(ss): @@ -285,6 +292,7 @@ def save(self, *args): raise NotImplementedError def select(self, **kwargs): + "Run 'select' on all indices within this MultiIndex." new_idx_list = [] new_src_list = [] for idx, src in zip(self.index_list, self.source_list): diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index 1dcacdfdcd..5c13218534 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -173,10 +173,10 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0, containment=False): "Selector interface - make sure this database matches requirements." if num: - raise ValueError("cannot use num MinHashes on LCA database") + raise ValueError("cannot use 'num' MinHashes to search LCA database") if scaled > self.scaled and not containment: - raise ValueError(f"cannot use scaled={scaled} on this database ({self.scaled})") + raise ValueError(f"cannot use scaled={scaled} on this database (scaled={self.scaled})") if ksize is not None and self.ksize != ksize: raise ValueError(f"ksize on this database is {self.ksize}; this is different from requested ksize of {ksize}") diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 74ef736f32..c29fbd8d8f 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -191,20 +191,27 @@ def signatures(self): def select(self, ksize=None, moltype=None, num=0, scaled=0, containment=False): + "Make sure this database matches requirements." + # pull out a signature from this collection - first_sig = next(iter(self.signatures())) db_mh = first_sig.minhash + # check ksize. if ksize is not None and db_mh.ksize != ksize: raise ValueError(f"search ksize {ksize} is different from database ksize {db_mh.ksize}") + + # check moltype. if moltype is not None and db_mh.moltype != moltype: raise ValueError(f"search moltype {moltype} is different from database moltype {db_mh.moltype}") + # containment requires 'scaled'. if containment: if not scaled: raise ValueError("'containment' requires 'scaled' in SBT.select'") if not db_mh.scaled: raise ValueError("cannot search this SBT for containment; signatures are not calculated with scaled") + # 'num' and 'scaled' do not mix. if num: if not db_mh.num: raise ValueError(f"this database was created with 'scaled' MinHash sketches, not 'num'") @@ -214,6 +221,8 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0, if scaled: if not db_mh.scaled: raise ValueError(f"this database was created with 'num' MinHash sketches, not 'scaled'") + + # we can downsample SBTs for containment operations. if scaled > db_mh.scaled and not containment: raise ValueError(f"search scaled value {scaled} is less than database scaled value of {db_mh.scaled}") From 2630be2e00e1583a13b87cf2673d943f1b20a823 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 08:05:30 -0700 Subject: [PATCH 64/71] remove all the cruft, yay --- src/sourmash/index.py | 76 ++++++++--------- src/sourmash/sourmash_args.py | 150 +++++----------------------------- 2 files changed, 59 insertions(+), 167 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index dcfa340ccb..fadb7dcebc 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -128,6 +128,37 @@ def select(self, ksize=None, moltype=None, scaled=None, num=None, abund=None, containment=None): "" + +def select_signature(ss, ksize=None, moltype=None, scaled=0, num=0, + containment=False): + # ksize match? + if ksize and ksize != ss.minhash.ksize: + return False + + # moltype match? + if moltype and moltype != ss.minhash.moltype: + return False + + # containment requires scaled; similarity does not. + if containment: + if not scaled: + raise ValueError("'containment' requires 'scaled' in Index.select'") + if not ss.minhash.scaled: + return False + + # 'scaled' and 'num' are incompatible + if scaled: + if ss.minhash.num: + return False + if num: + # note, here we check if 'num' is identical; this can be + # changed later. + if ss.minhash.scaled or num != ss.minhash.num: + return False + + return True + + class LinearIndex(Index): "An Index for a collection of signatures. Can load from a .sig file." def __init__(self, _signatures=None, filename=None): @@ -159,51 +190,20 @@ def load(cls, location): return lidx def select(self, **kwargs): - def select_sigs(ss): - # eliminate things from kwargs with no or zero - kw = { k : v for (k, v) in kwargs.items() if v } - - # nothing to select on? we're all good. - if not kw: - return True - - # ksize match? - if 'ksize' in kw and kw['ksize'] != ss.minhash.ksize: - return False - - # moltype match? - if 'moltype' in kw and kw['moltype'] != ss.minhash.moltype: - return False - - # containment requires scaled; similarity does not. - if 'containment' in kw: - if not 'scaled' in kw: - raise ValueError("'containment' requires 'scaled' in Index.select'") - if not ss.minhash.scaled: - return False - - # 'scaled' and 'num' are incompatible - if 'scaled' in kw: - if ss.minhash.num: - return False - if 'num' in kw: - # note, here we check if 'num' is identical; this can be - # changed later. - if ss.minhash.scaled or kw['num'] != ss.minhash.num: - return False - - return True - - return self.filter(select_sigs) + "Select signatures that match the given requirements. @CTB doc." + # eliminate things from kwargs with None or zero value + kw = { k : v for (k, v) in kwargs.items() if v } - def filter(self, filter_fn): # @CTB may not be necessary any more siglist = [] for ss in self._signatures: - if filter_fn(ss): + if select_signature(ss, **kwargs): siglist.append(ss) return LinearIndex(siglist, self.filename) + def filter(self, filter_fn): # @CTB may not be necessary any more + siglist = [] + class MultiIndex(Index): """An Index class that wraps other Index classes. diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index e9661cf3b3..601d532a58 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -141,63 +141,6 @@ def traverse_find_sigs(filenames, yield_all_files=False): yield fullname -def _check_signatures_are_compatible(query, subject): - # is one scaled, and the other not? cannot do search - if query.minhash.scaled and not subject.minhash.scaled or \ - not query.minhash.scaled and subject.minhash.scaled: - error("signature {} and {} are incompatible - cannot compare.", - query, subject) - if query.minhash.scaled: - error(f"{query} was calculated with --scaled, {subject} was not.") - if subject.minhash.scaled: - error(f"{subject} was calculated with --scaled, {query} was not.") - return 0 - - return 1 - - -def check_tree_is_compatible(treename, tree, query, is_similarity_query): - # get a minhash from the tree - leaf = next(iter(tree.leaves())) - tree_mh = leaf.data.minhash - - query_mh = query.minhash - - if tree_mh.ksize != query_mh.ksize: - error(f"ksize on tree '{treename}' is {tree_mh.ksize};") - error(f"this is different from query ksize of {query_mh.ksize}.") - return 0 - - # is one scaled, and the other not? cannot do search. - if (tree_mh.scaled and not query_mh.scaled) or \ - (query_mh.scaled and not tree_mh.scaled): - error(f"for tree '{treename}', tree and query are incompatible for search.") - if tree_mh.scaled: - error("tree was calculated with scaled, query was not.") - else: - error("query was calculated with scaled, tree was not.") - return 0 - - # are the scaled values incompatible? cannot downsample tree for similarity - if tree_mh.scaled and tree_mh.scaled < query_mh.scaled and \ - is_similarity_query: - error(f"for tree '{treename}', scaled value is smaller than query.") - error(f"tree scaled: {tree_mh.scaled}; query scaled: {query_mh.scaled}. Cannot do similarity search.") - return 0 - - return 1 - - -def check_lca_db_is_compatible(filename, db, query): - query_mh = query.minhash - if db.ksize != query_mh.ksize: - error(f"ksize on db '{filename}' is {db.ksize};") - error(f"this is different from query ksize of {query_mh.ksize}.") - return 0 - - return 1 - - def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None): """ Load one or more SBTs, LCAs, and/or signatures. @@ -205,8 +148,6 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) Check for compatibility with query. This is basically a user-focused wrapping of _load_databases. - - CTB: this can be refactored into a more generic function with 'filter'. """ query_ksize = query.minhash.ksize query_moltype = get_moltype(query) @@ -222,8 +163,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) notify(f'loading from {filename}...', end='\r') try: - db, dbtype = _load_database(filename, False, cache_size=cache_size) - except Exception as e: + db = _load_database(filename, False, cache_size=cache_size) + except Exception as e: # @CTB too broad an exception clause!? notify(str(e)) sys.exit(-1) @@ -234,60 +175,21 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) scaled=query.minhash.scaled, containment=containment) except ValueError as exc: + # incompatible collection specified! notify(f"ERROR: cannot use '{filename}' for this query.") notify(str(exc)) sys.exit(-1) + # 'select' returns nothing => all signatures filtered out. fail! if not db: notify(f"no compatible signatures found in '{filename}'") sys.exit(-1) databases.append(db) - if 0: - # are we collecting signatures from an SBT? - if dbtype == DatabaseType.SBT: - if not check_tree_is_compatible(filename, db, query, - is_similarity_query): - sys.exit(-1) - - databases.append(db) - notify(f'loaded SBT {filename}', end='\r') - n_databases += 1 - - # or an LCA? - elif dbtype == DatabaseType.LCA: - if not check_lca_db_is_compatible(filename, db, query): - sys.exit(-1) - - notify(f'loaded LCA {filename}', end='\r') - n_databases += 1 - - databases.append(db) - - # or a mixed collection of signatures? - elif dbtype == DatabaseType.SIGLIST: - db = db.select(moltype=query_moltype, ksize=query_ksize) - filter_fn = lambda s: _check_signatures_are_compatible(query, s) - db = db.filter(filter_fn) - - if not db: - notify(f"no compatible signatures found in '{filename}'") - sys.exit(-1) - - databases.append(db) - - notify(f'loaded {len(db)} signatures from {filename}', end='\r') - n_signatures += len(db) - - # unknown!? - else: - raise ValueError(f"unknown dbtype {dbtype}") # CTB check me. - - # END for loop - notify(' '*79, end='\r') + # @CTB update below messages. if n_signatures and n_databases: notify(f'loaded {n_signatures} signatures and {n_databases} databases total.') elif n_signatures: @@ -295,37 +197,29 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) elif n_databases: notify(f'loaded {n_databases} databases.') - - if not databases: - notify('** ERROR: no signatures or databases loaded?') - sys.exit(-1) - if databases: print('') + else: + notify('** ERROR: no signatures or databases loaded?') + sys.exit(-1) return databases -class DatabaseType(Enum): - SIGLIST = 1 - SBT = 2 - LCA = 3 - - def _load_stdin(filename, **kwargs): "Load collection from .sig file streamed in via stdin" db = None if filename == '-': db = LinearIndex.load(sys.stdin) - return (db, DatabaseType.SIGLIST) + return db def _multiindex_load_from_file_list(filename, **kwargs): "Load collection from a list of signature/database files" db = MultiIndex.load_from_file_list(filename) - return (db, DatabaseType.SIGLIST) + return db def _multiindex_load_from_path(filename, **kwargs): @@ -333,7 +227,7 @@ def _multiindex_load_from_path(filename, **kwargs): traverse_yield_all = kwargs['traverse_yield_all'] db = MultiIndex.load_from_path(filename, traverse_yield_all) - return (db, DatabaseType.SIGLIST) + return db def _load_sigfile(filename, **kwargs): @@ -343,7 +237,7 @@ def _load_sigfile(filename, **kwargs): except sourmash.exceptions.SourmashError as exc: raise ValueError(exc) - return (db, DatabaseType.SIGLIST) + return db def _load_sbt(filename, **kwargs): @@ -355,13 +249,13 @@ def _load_sbt(filename, **kwargs): except FileNotFoundError as exc: raise ValueError(exc) - return (db, DatabaseType.SBT) + return db def _load_revindex(filename, **kwargs): "Load collection from an LCA database/reverse index." db, _, _ = load_single_database(filename) - return (db, DatabaseType.LCA) + return db # all loader functions, in order. @@ -378,21 +272,20 @@ def _load_revindex(filename, **kwargs): def _load_database(filename, traverse_yield_all, *, cache_size=None): """Load file as a database - list of signatures, LCA, SBT, etc. - Return (db, dbtype), where dbtype is a DatabaseType enum. + Return Index object. This is an internal function used by other functions in sourmash_args. """ loaded = False - dbtype = None # iterate through loader functions, trying them all. Catch ValueError # but nothing else. for (desc, load_fn) in _loader_functions: try: debug_literal(f"_load_databases: trying loader fn {desc}") - db, dbtype = load_fn(filename, - traverse_yield_all=traverse_yield_all, - cache_size=cache_size) + db = load_fn(filename, + traverse_yield_all=traverse_yield_all, + cache_size=cache_size) except ValueError as exc: debug_literal(f"_load_databases: FAIL on fn {desc}.") debug_literal(traceback.format_exc()) @@ -424,7 +317,7 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): if loaded: # this is a bit redundant but safe > sorry assert db - return db, dbtype + return db def load_file_as_index(filename, yield_all_files=False): @@ -440,8 +333,7 @@ def load_file_as_index(filename, yield_all_files=False): this directory into an Index object. If yield_all_files=True, will attempt to load all files. """ - db, dbtype = _load_database(filename, yield_all_files) - return db + return _load_database(filename, yield_all_files) def load_file_as_signatures(filename, select_moltype=None, ksize=None, @@ -464,7 +356,7 @@ def load_file_as_signatures(filename, select_moltype=None, ksize=None, if progress: progress.notify(filename) - db, dbtype = _load_database(filename, yield_all_files) + db = _load_database(filename, yield_all_files) db = db.select(moltype=select_moltype, ksize=ksize) loader = db.signatures() From 4f1a7fe22853232df5f3f2bb3ce5762cf0e41504 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 08:11:53 -0700 Subject: [PATCH 65/71] added 'is_database' flag for nicer UX --- src/sourmash/index.py | 2 ++ src/sourmash/lca/lca_db.py | 2 ++ src/sourmash/sbt.py | 1 + src/sourmash/sourmash_args.py | 26 +++++++++++++++----------- tests/test_sourmash.py | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index fadb7dcebc..8f2b7ab9c7 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -7,6 +7,8 @@ class Index(ABC): + is_database = False + @abstractmethod def signatures(self): "Return an iterator over all signatures in the Index object." diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index 5c13218534..eb270e767b 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -55,6 +55,8 @@ class LCA_Database(Index): `hashval_to_idx` is a dictionary from individual hash values to sets of `idx`. """ + is_database = True + def __init__(self, ksize, scaled, moltype='DNA'): self.ksize = int(ksize) self.scaled = int(scaled) diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index c29fbd8d8f..384b352e10 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -171,6 +171,7 @@ class SBT(Index): We use two dicts to store the tree structure: One for the internal nodes, and another for the leaves (datasets). """ + is_database = True def __init__(self, factory, *, d=2, storage=None, cache_size=None): self.factory = factory diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 601d532a58..9e6c436885 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -149,15 +149,12 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) This is basically a user-focused wrapping of _load_databases. """ - query_ksize = query.minhash.ksize - query_moltype = get_moltype(query) + query_mh = query.minhash containment = True if is_similarity_query: containment = False - n_signatures = 0 - n_databases = 0 databases = [] for filename in filenames: notify(f'loading from {filename}...', end='\r') @@ -169,10 +166,10 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) sys.exit(-1) try: - db = db.select(moltype=query_moltype, - ksize=query_ksize, - num=query.minhash.num, - scaled=query.minhash.scaled, + db = db.select(moltype=query_mh.moltype, + ksize=query_mh.ksize, + num=query_mh.num, + scaled=query_mh.scaled, containment=containment) except ValueError as exc: # incompatible collection specified! @@ -187,14 +184,21 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) databases.append(db) + # calc num loaded info. + n_signatures = 0 + n_databases = 0 + for db in databases: + if db.is_database: + n_databases += 1 + else: + n_signatures += len(db) notify(' '*79, end='\r') - # @CTB update below messages. if n_signatures and n_databases: notify(f'loaded {n_signatures} signatures and {n_databases} databases total.') - elif n_signatures: + elif n_signatures and not n_databases: notify(f'loaded {n_signatures} signatures.') - elif n_databases: + elif n_databases and not n_signatures: notify(f'loaded {n_databases} databases.') if databases: diff --git a/tests/test_sourmash.py b/tests/test_sourmash.py index ca520e05ad..deb1b667cb 100644 --- a/tests/test_sourmash.py +++ b/tests/test_sourmash.py @@ -3780,7 +3780,7 @@ def test_gather_query_downsample(): print(out) print(err) - # assert 'loaded 12 signatures' in err @CTB + assert 'loaded 12 signatures' in err assert all(('4.9 Mbp 100.0% 100.0%' in out, 'NC_003197.2' in out)) From 736ddf3b9b4f17580d0a6b340b0b0dcd6ca42faf Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 09:46:02 -0700 Subject: [PATCH 66/71] remove overly broad exception catching --- src/sourmash/sourmash_args.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 9e6c436885..d8525a3fd4 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -161,7 +161,8 @@ def load_dbs_and_sigs(filenames, query, is_similarity_query, *, cache_size=None) try: db = _load_database(filename, False, cache_size=cache_size) - except Exception as e: # @CTB too broad an exception clause!? + except ValueError as e: + # cannot load database! notify(str(e)) sys.exit(-1) From 16719ce967aedab4815cfaa97e9c737023215896 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 09:58:52 -0700 Subject: [PATCH 67/71] add docstrings --- src/sourmash/index.py | 25 ++++++++++++++++++++----- src/sourmash/lca/lca_db.py | 5 ++++- src/sourmash/sbt.py | 5 ++++- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index 8f2b7ab9c7..44e108cc1f 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -128,11 +128,26 @@ def gather(self, query, *args, **kwargs): @abstractmethod def select(self, ksize=None, moltype=None, scaled=None, num=None, abund=None, containment=None): - "" + """Return Index containing only signatures that match requirements. + + Current arguments can be any or all of: + * ksize + * moltype + * scaled + * num + * containment + + 'select' will raise ValueError if the requirements are incompatible + with the Index subclass. + + 'select' may return an empty object or None if no matches can be + found. + """ def select_signature(ss, ksize=None, moltype=None, scaled=0, num=0, containment=False): + "Check that the given signature matches the specificed requirements." # ksize match? if ksize and ksize != ss.minhash.ksize: return False @@ -192,7 +207,10 @@ def load(cls, location): return lidx def select(self, **kwargs): - "Select signatures that match the given requirements. @CTB doc." + """Return new LinearIndex containing only signatures that match req's. + + Does not raise ValueError, but may return an empty Index. + """ # eliminate things from kwargs with None or zero value kw = { k : v for (k, v) in kwargs.items() if v } @@ -203,9 +221,6 @@ def select(self, **kwargs): return LinearIndex(siglist, self.filename) - def filter(self, filter_fn): # @CTB may not be necessary any more - siglist = [] - class MultiIndex(Index): """An Index class that wraps other Index classes. diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index eb270e767b..b4b4ef26b5 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -173,7 +173,10 @@ def signatures(self): def select(self, ksize=None, moltype=None, num=0, scaled=0, containment=False): - "Selector interface - make sure this database matches requirements." + """Make sure this database matches the requested requirements. + + Will always raise ValueError if a requirement cannot be met. + """ if num: raise ValueError("cannot use 'num' MinHashes to search LCA database") diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 384b352e10..0194f741d5 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -192,7 +192,10 @@ def signatures(self): def select(self, ksize=None, moltype=None, num=0, scaled=0, containment=False): - "Make sure this database matches requirements." + """Make sure this database matches the requested requirements. + + Will always raise ValueError if a requirement cannot be met. + """ # pull out a signature from this collection - first_sig = next(iter(self.signatures())) db_mh = first_sig.minhash From 6d8663e13de498546e3cf92c0be3c097c8fa2b86 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Wed, 31 Mar 2021 10:35:57 -0700 Subject: [PATCH 68/71] document downsampling foo --- src/sourmash/lca/lca_db.py | 11 ++++++++++- src/sourmash/sbt.py | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/sourmash/lca/lca_db.py b/src/sourmash/lca/lca_db.py index b4b4ef26b5..03e22dc8a2 100644 --- a/src/sourmash/lca/lca_db.py +++ b/src/sourmash/lca/lca_db.py @@ -175,6 +175,11 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0, containment=False): """Make sure this database matches the requested requirements. + As with SBTs, queries with higher scaled values than the database + can still be used for containment search, but not for similarity + search. See SBT.select(...) for details, and _find_signatures for + implementation. + Will always raise ValueError if a requirement cannot be met. """ if num: @@ -475,12 +480,16 @@ def _find_signatures(self, minhash, threshold, containment=False, This is essentially a fast implementation of find that collects all the signatures with overlapping hash values. Note that similarity searches (containment=False) will not be returned in sorted order. + + As with SBTs, queries with higher scaled values than the database + can still be used for containment search, but not for similarity + search. See SBT.select(...) for details. """ # make sure we're looking at the same scaled value as database if self.scaled > minhash.scaled: minhash = minhash.downsample(scaled=self.scaled) elif self.scaled < minhash.scaled and not ignore_scaled: - # note that containment cannot be calculated w/o matching scaled. + # note that similarity cannot be calculated w/o matching scaled. raise ValueError("lca db scaled is {} vs query {}; must downsample".format(self.scaled, minhash.scaled)) query_mins = set(minhash.hashes) diff --git a/src/sourmash/sbt.py b/src/sourmash/sbt.py index 0194f741d5..fa22507961 100644 --- a/src/sourmash/sbt.py +++ b/src/sourmash/sbt.py @@ -195,6 +195,19 @@ def select(self, ksize=None, moltype=None, num=0, scaled=0, """Make sure this database matches the requested requirements. Will always raise ValueError if a requirement cannot be met. + + The only tricky bit here is around downsampling: if the scaled + value being requested is higher than the signatures in the + SBT, we can use the SBT for containment but not for + similarity. This is because: + + * if we are doing containment searches, the intermediate nodes + can still be used for calculating containment of signatures + with higher scaled values. This is because only hashes that match + in the higher range are used for containment scores. + * however, for similarity, _all_ hashes are used, and we cannot + implicitly downsample or necessarily estimate similarity if + the scaled values differ. """ # pull out a signature from this collection - first_sig = next(iter(self.signatures())) From c4de8fbf7537cbd89a7d4003d4665e6e21324793 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Thu, 1 Apr 2021 07:20:28 -0700 Subject: [PATCH 69/71] update for additional test files --- tests/test_index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_index.py b/tests/test_index.py index db0bf91f42..1cca765ebe 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -716,7 +716,7 @@ def test_multi_index_load_from_path_3_check_traverse_fn(c): assert len(files) == 6, files files = list(sourmash_args.traverse_find_sigs([dirname], True)) - assert len(files) == 14, files + assert len(files) == 18, files def test_multi_index_load_from_path_no_exist(): @@ -751,7 +751,7 @@ def test_multi_index_load_from_file_list_1(c): def test_multi_index_load_from_file_list_2(c): dirname = utils.get_test_data('prot') files = list(sourmash_args.traverse_find_sigs([dirname], True)) - assert len(files) == 14, files + assert len(files) == 18, files file_list = c.output('filelist.txt') From 31194bfe4f744e70591a71207bd1b0464af5345e Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Thu, 1 Apr 2021 07:20:48 -0700 Subject: [PATCH 70/71] update ZipFileLinearIndex for new selector criteria --- src/sourmash/index.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/sourmash/index.py b/src/sourmash/index.py index e1128aa72d..5fda09a456 100644 --- a/src/sourmash/index.py +++ b/src/sourmash/index.py @@ -229,11 +229,12 @@ class ZipFileLinearIndex(Index): Does not support `insert` or `save`. """ - def __init__(self, zf, select_ksize=None, select_moltype=None, + is_database = True + + def __init__(self, zf, selection_dict=None, traverse_yield_all=False): self.zf = zf - self.ksize = select_ksize - self.moltype = select_moltype + self.selection_dict = selection_dict self.traverse_yield_all = traverse_yield_all @property @@ -261,15 +262,19 @@ def signatures(self): fp = self.zf.open(zipinfo) # now load all the signatures and select on ksize/moltype: + selection_dict = self.selection_dict for ss in load_signatures(fp): - if (self.ksize is None or ss.minhash.ksize == self.ksize) and \ - (self.moltype is None or ss.minhash.moltype == self.moltype): + if selection_dict: + if select_signature(ss, **self.selection_dict): + yield ss + else: yield ss - def select(self, ksize=None, moltype=None): + def select(self, **kwargs): "Select signatures in zip file based on ksize/moltype." - return ZipFileLinearIndex(self.zf, ksize, moltype, - self.traverse_yield_all) + return ZipFileLinearIndex(self.zf, + selection_dict=kwargs, + traverse_yield_all=self.traverse_yield_all) class MultiIndex(Index): From be502abb152c36c1cbcec471c9b7c12e0af8a2f5 Mon Sep 17 00:00:00 2001 From: "C. Titus Brown" Date: Thu, 1 Apr 2021 07:25:12 -0700 Subject: [PATCH 71/71] remove leftover code fragment --- src/sourmash/sourmash_args.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/sourmash/sourmash_args.py b/src/sourmash/sourmash_args.py index 9218d9b5c9..52a504500a 100644 --- a/src/sourmash/sourmash_args.py +++ b/src/sourmash/sourmash_args.py @@ -310,17 +310,6 @@ def _load_database(filename, traverse_yield_all, *, cache_size=None): loaded = True break - if not loaded: # try load as ZipFileLinearIndex - if filename.endswith('.zip'): - try: - db = ZipFileLinearIndex.load(filename, - traverse_yield_all=traverse_yield_all) - loaded = True - dbtype = DatabaseType.ZIPFILE - except: - raise - pass - # check to see if it's a FASTA/FASTQ record (i.e. screed loadable) # so we can provide a better error message to users. if not loaded: