diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 24ceefe..437617b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_. +1.6.0 +----- +- Added ability to parse second upstream / downstream region in ``IlluminaBarcodeParser`` by adding ``upstream2`` and ``downstream2`` parameters. Also modified ``IlluminaBarcodeParser`` so that reads will only be parsed if they are long enough to fully cover the region containing the barcodes and specified upstream / downstream sequences. Based on docs, this is how it was supposed to function before but did not. Additionally, this adds another row ("reads too short") to the fates from the barcode parser, as well as the ``outer_flank_fates`` option to report just failing the additional upstream and downstream regions. +- Change default color of heatmaps made by ``CodonVariantTable`` due to current one being obsolete. +- Remove obsolete ``guide=False`` from some ``plotnine`` plots in examples / tests (this was removed in ``plotnine`` version 0.13). + 1.5.0 ----- - Remove use of deprecated ``scipy`` functions like ``flip`` to use ``numpy`` alternatives instead (fixes [this issue](https://github.com/jbloomlab/dms_variants/issues/86)). diff --git a/dms_variants/__init__.py b/dms_variants/__init__.py index db24f4b..1538f11 100644 --- a/dms_variants/__init__.py +++ b/dms_variants/__init__.py @@ -10,5 +10,5 @@ __author__ = "`the Bloom lab `_" __email__ = "jbloom@fredhutch.org" -__version__ = "1.5.0" +__version__ = "1.6.0" __url__ = "https://github.com/jbloomlab/dms_variants" diff --git a/dms_variants/codonvarianttable.py b/dms_variants/codonvarianttable.py index 1db8132..7665566 100644 --- a/dms_variants/codonvarianttable.py +++ b/dms_variants/codonvarianttable.py @@ -1934,7 +1934,6 @@ def plotMutHeatmap( expand=(0, 0), ) + p9.ylab(mut_desc) - + p9.scale_fill_cmap("gnuplot") ) if samples is None: @@ -1999,7 +1998,7 @@ def plotMutFreqs( assert "target" not in set(df.columns).union(set(n_variants.columns)) df = ( - df.groupby(["library", "sample", "mutation_type", "site"]) + df.groupby(["library", "sample", "mutation_type", "site"], observed=False) .aggregate({"count": "sum"}) .reset_index() .merge(n_variants, on=["library", "sample"]) diff --git a/dms_variants/illuminabarcodeparser.py b/dms_variants/illuminabarcodeparser.py index 3eef2f7..26e7da8 100644 --- a/dms_variants/illuminabarcodeparser.py +++ b/dms_variants/illuminabarcodeparser.py @@ -30,7 +30,7 @@ class IlluminaBarcodeParser: ---- Barcodes should be read by R1 and optionally R2. Expected arrangement is - 5'-[R2_start]-upstream-barcode-downstream-[R1_start]-3' + 5'-[R2_start]-upstream2-upstream-barcode-downstream-downstream2-[R1_start]-3' R1 anneals downstream of barcode and reads backwards. If R2 is used, it anneals upstream of barcode and reads forward. There can be sequences @@ -38,7 +38,11 @@ class IlluminaBarcodeParser: must fully cover region between R1 start and barcode, and if using R2 then `upstream` must fully cover region between R2 start and barcode. However, it is fine if R1 reads backwards past `upstream`, and if `R2` - reads forward past `downstream`. + reads forward past `downstream`. The `upstream2` and `downstream2` + can be used to require additional flanking sequences. Normally these + would just be rolled into `upstream` and `downstream`, but you might + specify separately if you are actually using these to parse additional + indices that you might want to set different mismatch criteria for. Parameters ---------- @@ -72,12 +76,20 @@ class IlluminaBarcodeParser: Length of barcodes. upstream : str Sequence upstream of barcode. + upstream2 : str + Second sequence upstream of barcode. downstream : str Sequence downstream of barcode. + downstream2 : str + Second sequence downstream of barcode upstream_mismatch : int Max number of mismatches allowed in `upstream`. + upstream2_mismatch : int + Max number of mismatches allowed in `upstream2`. downstream_mismatch : int Max number of mismatches allowed in `downstream`. + downstream2_mismatch : int + Max number of mismatches allowed in `downstream2`. valid_barcodes : None or set If not `None`, set of barcodes to retain. bc_orientation : {'R1', 'R2'} @@ -101,9 +113,13 @@ def __init__( *, bclen=None, upstream="", + upstream2="", downstream="", + downstream2="", upstream_mismatch=0, + upstream2_mismatch=0, downstream_mismatch=0, + downstream2_mismatch=0, valid_barcodes=None, bc_orientation="R1", minq=20, @@ -112,16 +128,20 @@ def __init__( ): """See main class doc string.""" self.bclen = bclen - if regex.match(f"^[{self.VALID_NTS}]*$", upstream): - self.upstream = upstream - else: - raise ValueError(f"invalid chars in upstream {upstream}") - if regex.match(f"^[{self.VALID_NTS}]*$", downstream): - self.downstream = downstream - else: - raise ValueError(f"invalid chars in downstream {downstream}") + for param_name, param_val in [ + ("upstream", upstream), + ("downstream", downstream), + ("upstream2", upstream2), + ("downstream2", downstream2), + ]: + if regex.match(f"^[{self.VALID_NTS}]*$", param_val): + setattr(self, param_name, param_val) + else: + raise ValueError(f"invalid chars in {param_name} {param_val}") self.upstream_mismatch = upstream_mismatch self.downstream_mismatch = downstream_mismatch + self.upstream2_mismatch = upstream2_mismatch + self.downstream2_mismatch = downstream2_mismatch self.valid_barcodes = valid_barcodes if self.valid_barcodes is not None: self.valid_barcodes = set(self.valid_barcodes) @@ -142,15 +162,61 @@ def __init__( self.list_all_valid_barcodes = list_all_valid_barcodes # specify information about R1 / R2 matches - self._bcend = { - "R1": self.bclen + len(self.downstream), - "R2": self.bclen + len(self.upstream), - } self._rcdownstream = reverse_complement(self.downstream) self._rcupstream = reverse_complement(self.upstream) - self._matches = {"R1": {}, "R2": {}} # match objects by read length + self._rcdownstream2 = reverse_complement(self.downstream2) + self._rcupstream2 = reverse_complement(self.upstream2) + + # build the regex read matches + self._matchers = { + "R1": regex.compile( + f"({self._rcdownstream2})" + + f"{{s<={self.downstream2_mismatch}}}" + + f"({self._rcdownstream})" + + f"{{s<={self.downstream_mismatch}}}" + + f"(?P[ACTG]{{{self.bclen}}})" + + f"({self._rcupstream})" + + f"{{s<={self.upstream_mismatch}}}" + + f"({self._rcupstream2})" + + f"{{s<={self.upstream2_mismatch}}}" + ), + "R2": regex.compile( + f"({self.upstream2})" + + f"{{s<={self.upstream2_mismatch}}}" + + f"({self.upstream})" + + f"{{s<={self.upstream_mismatch}}}" + + f"(?P[ACTG]{{{self.bclen}}})" + + f"({self.downstream})" + + f"{{s<={self.downstream_mismatch}}}" + + f"({self.downstream2})" + + f"{{s<={self.downstream2_mismatch}}}" + ), + } + + # build matchers that do not have upstream2 or downstream2 if needed + self._has_flank2 = (len(self.upstream2) > 0) or (len(self.downstream2) > 0) + self._matchers_no_flank2 = { + "R1": regex.compile( + f"[{self.VALID_NTS}]{{{len(self.downstream2)}}}" + + f"({self._rcdownstream})" + + f"{{s<={self.downstream_mismatch}}}" + + f"(?P[ACTG]{{{self.bclen}}})" + + f"({self._rcupstream})" + + f"{{s<={self.upstream_mismatch}}}" + + f"[{self.VALID_NTS}]{{{len(self.upstream2)}}}" + ), + "R2": regex.compile( + f"[{self.VALID_NTS}]{{{len(self.upstream2)}}}" + + f"^({self.upstream})" + + f"{{s<={self.upstream_mismatch}}}" + + f"(?P[ACTG]{{{self.bclen}}})" + + f"({self.downstream})" + + f"{{s<={self.downstream_mismatch}}}" + + f"[{self.VALID_NTS}]{{{len(self.downstream2)}}}" + ), + } - def parse(self, r1files, *, r2files=None, add_cols=None): + def parse(self, r1files, *, r2files=None, add_cols=None, outer_flank_fates=False): """Parse barcodes from files. Parameters @@ -162,6 +228,11 @@ def parse(self, r1files, *, r2files=None, add_cols=None): add_cols : None or dict If dict, specify names and values (i.e., sample or library names) to be aded to returned data frames. + outer_flank_fates : bool + If `True`, if using outer flanking regions then in the output fates + specify reads that fail just the outer flanking regions (`upstream2` or + `downstream2`). Otherwise, such failures will be grouped with the + "unparseable barcode" fate. Returns ------- @@ -177,6 +248,9 @@ def parse(self, r1files, *, r2files=None, add_cols=None): - "R1 / R2 disagree" (if using `r2files`) - "low quality barcode": sequencing quality low - "unparseable barcode": invalid flank sequence, N in barcode + - "read too short": read is too short to cover specified region + - "invalid outer flank" : if using `outer_flank_fates` and + `upstream2` or `downstream2` fails. Note that these data frames also include any columns specified by `add_cols`. @@ -210,21 +284,30 @@ def parse(self, r1files, *, r2files=None, add_cols=None): "low quality barcode": 0, "invalid barcode": 0, "valid barcode": 0, + "read too short": 0, } if not r1only: fates["R1 / R2 disagree"] = 0 - - # max length of interest for reads - max_len = self.bclen + len(self.upstream) + len(self.downstream) + if outer_flank_fates and self._has_flank2: + fates["invalid outer flank"] = 0 + + # min length of interest for reads + minlen = ( + self.bclen + + len(self.upstream) + + len(self.downstream) + + len(self.upstream2) + + len(self.downstream2) + ) for filetup in zip(*fileslist): if r1only: assert len(filetup) == 1 - iterator = iterate_fastq(filetup[0], check_pair=1, trim=max_len) + iterator = iterate_fastq(filetup[0], check_pair=1, trim=minlen) else: assert len(filetup) == 2, f"{filetup}\n{fileslist}" iterator = iterate_fastq_pair( - filetup[0], filetup[1], r1trim=max_len, r2trim=max_len + filetup[0], filetup[1], r1trim=minlen, r2trim=minlen ) for entry in iterator: @@ -242,44 +325,18 @@ def parse(self, r1files, *, r2files=None, add_cols=None): fates["failed chastity filter"] += 1 continue - matches = {} - for read, r in zip(reads, readlist): - rlen = len(r) + if any(len(r) < minlen for r in readlist): + fates["read too short"] += 1 + continue - # get or build matcher for read of this length - len_past_bc = rlen - self._bcend[read] - if len_past_bc < 0: - raise ValueError(f"{read} too short: {rlen}") - elif rlen in self._matches[read]: - matcher = self._matches[read][rlen] - else: - if read == "R1": - match_str = ( - f"^({self._rcdownstream})" - f"{{s<={self.downstream_mismatch}}}" - f"(?P[ACTG]{{{self.bclen}}})" - f"({self._rcupstream[: len_past_bc]})" - f"{{s<={self.upstream_mismatch}}}" - ) - else: - assert read == "R2" - match_str = ( - f"^({self.upstream})" - f"{{s<={self.upstream_mismatch}}}" - f"(?P[ACTG]{{{self.bclen}}})" - f"({self.downstream[: len_past_bc]})" - f"{{s<={self.downstream_mismatch}}}" - ) - matcher = regex.compile(match_str, flags=regex.BESTMATCH) - self._matches[read][rlen] = matcher - - m = matcher.match(r) - if m: - matches[read] = m - else: - break + assert all(len(r) == minlen for r in readlist) + + matches = { + read: self._matchers[read].fullmatch(r) + for (read, r) in zip(reads, readlist) + } - if len(matches) == len(reads): + if all(m is not None for m in matches.values()): bc = {} bc_q = {} for read, q in zip(reads, qlist): @@ -321,6 +378,15 @@ def parse(self, r1files, *, r2files=None, add_cols=None): fates["low quality barcode"] += 1 else: fates["R1 / R2 disagree"] += 1 + elif ( + outer_flank_fates + and self._has_flank2 + and all( + self._matchers_no_flank2[read].fullmatch(r) is not None + for (read, r) in zip(reads, readlist) + ) + ): + fates["invalid outer flank"] += 1 else: # invalid flanking sequence or N in barcode fates["unparseable barcode"] += 1 diff --git a/notebooks/codonvariant_sim_data.ipynb b/notebooks/codonvariant_sim_data.ipynb index a2ac6af..51aef91 100644 --- a/notebooks/codonvariant_sim_data.ipynb +++ b/notebooks/codonvariant_sim_data.ipynb @@ -3584,7 +3584,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw(show=True)" ] diff --git a/notebooks/codonvariant_sim_data_multi_targets.ipynb b/notebooks/codonvariant_sim_data_multi_targets.ipynb index 8b95145..226b3cc 100644 --- a/notebooks/codonvariant_sim_data_multi_targets.ipynb +++ b/notebooks/codonvariant_sim_data_multi_targets.ipynb @@ -5430,7 +5430,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "\n", "_ = p.draw(show=True)" diff --git a/notebooks/multi_latent_phenos.ipynb b/notebooks/multi_latent_phenos.ipynb index e1e5b0e..bde24eb 100644 --- a/notebooks/multi_latent_phenos.ipynb +++ b/notebooks/multi_latent_phenos.ipynb @@ -768,7 +768,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw(show=True)" ] diff --git a/notebooks/narrow_bottleneck.ipynb b/notebooks/narrow_bottleneck.ipynb index ab08e57..b56f35c 100644 --- a/notebooks/narrow_bottleneck.ipynb +++ b/notebooks/narrow_bottleneck.ipynb @@ -835,7 +835,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw(show=True)" ] diff --git a/notebooks/parsebarcodes_sim_data.ipynb b/notebooks/parsebarcodes_sim_data.ipynb index e7cc757..9f67cd7 100644 --- a/notebooks/parsebarcodes_sim_data.ipynb +++ b/notebooks/parsebarcodes_sim_data.ipynb @@ -26,6 +26,13 @@ "classes": [], "id": "", "n": "1" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:40.815432Z", + "iopub.status.busy": "2024-04-10T20:05:40.814366Z", + "iopub.status.idle": "2024-04-10T20:05:44.954972Z", + "shell.execute_reply": "2024-04-10T20:05:44.954174Z", + "shell.execute_reply.started": "2024-04-10T20:05:40.815379Z" } }, "outputs": [], @@ -61,6 +68,13 @@ "classes": [], "id": "", "n": "3" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:44.958831Z", + "iopub.status.busy": "2024-04-10T20:05:44.958529Z", + "iopub.status.idle": "2024-04-10T20:05:44.961978Z", + "shell.execute_reply": "2024-04-10T20:05:44.961384Z", + "shell.execute_reply.started": "2024-04-10T20:05:44.958804Z" } }, "outputs": [], @@ -83,6 +97,13 @@ "classes": [], "id": "", "n": "5" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:44.965486Z", + "iopub.status.busy": "2024-04-10T20:05:44.965154Z", + "iopub.status.idle": "2024-04-10T20:05:44.968603Z", + "shell.execute_reply": "2024-04-10T20:05:44.968002Z", + "shell.execute_reply.started": "2024-04-10T20:05:44.965457Z" } }, "outputs": [], @@ -100,7 +121,15 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:44.972410Z", + "iopub.status.busy": "2024-04-10T20:05:44.971869Z", + "iopub.status.idle": "2024-04-10T20:05:44.977782Z", + "shell.execute_reply": "2024-04-10T20:05:44.977077Z", + "shell.execute_reply.started": "2024-04-10T20:05:44.972378Z" + } + }, "outputs": [], "source": [ "theme_set(dms_variants.plotnine_themes.theme_graygrid())" @@ -124,6 +153,13 @@ "classes": [], "id": "", "n": "6" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:44.981199Z", + "iopub.status.busy": "2024-04-10T20:05:44.980887Z", + "iopub.status.idle": "2024-04-10T20:05:45.004497Z", + "shell.execute_reply": "2024-04-10T20:05:45.003961Z", + "shell.execute_reply.started": "2024-04-10T20:05:44.981171Z" } }, "outputs": [], @@ -153,6 +189,13 @@ "classes": [], "id": "", "n": "8" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.007722Z", + "iopub.status.busy": "2024-04-10T20:05:45.007435Z", + "iopub.status.idle": "2024-04-10T20:05:45.022236Z", + "shell.execute_reply": "2024-04-10T20:05:45.021685Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.007698Z" } }, "outputs": [ @@ -275,7 +318,15 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.025335Z", + "iopub.status.busy": "2024-04-10T20:05:45.025036Z", + "iopub.status.idle": "2024-04-10T20:05:45.029102Z", + "shell.execute_reply": "2024-04-10T20:05:45.028494Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.025309Z" + } + }, "outputs": [ { "name": "stdout", @@ -301,7 +352,15 @@ { "cell_type": "code", "execution_count": 8, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.032391Z", + "iopub.status.busy": "2024-04-10T20:05:45.032082Z", + "iopub.status.idle": "2024-04-10T20:05:45.042341Z", + "shell.execute_reply": "2024-04-10T20:05:45.041684Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.032363Z" + } + }, "outputs": [ { "data": { @@ -384,7 +443,15 @@ { "cell_type": "code", "execution_count": 9, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.045607Z", + "iopub.status.busy": "2024-04-10T20:05:45.045302Z", + "iopub.status.idle": "2024-04-10T20:05:45.050103Z", + "shell.execute_reply": "2024-04-10T20:05:45.049529Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.045581Z" + } + }, "outputs": [], "source": [ "barcode_seqs = []\n", @@ -404,7 +471,15 @@ { "cell_type": "code", "execution_count": 10, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.053294Z", + "iopub.status.busy": "2024-04-10T20:05:45.052987Z", + "iopub.status.idle": "2024-04-10T20:05:45.057238Z", + "shell.execute_reply": "2024-04-10T20:05:45.056639Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.053267Z" + } + }, "outputs": [], "source": [ "n_invalid = 3\n", @@ -423,7 +498,15 @@ { "cell_type": "code", "execution_count": 11, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.060813Z", + "iopub.status.busy": "2024-04-10T20:05:45.060433Z", + "iopub.status.idle": "2024-04-10T20:05:45.064295Z", + "shell.execute_reply": "2024-04-10T20:05:45.063634Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.060785Z" + } + }, "outputs": [], "source": [ "n_unparseable = 2\n", @@ -442,7 +525,15 @@ { "cell_type": "code", "execution_count": 12, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.067729Z", + "iopub.status.busy": "2024-04-10T20:05:45.067406Z", + "iopub.status.idle": "2024-04-10T20:05:45.070818Z", + "shell.execute_reply": "2024-04-10T20:05:45.070140Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.067700Z" + } + }, "outputs": [], "source": [ "minq = 20\n", @@ -459,7 +550,15 @@ { "cell_type": "code", "execution_count": 13, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.077081Z", + "iopub.status.busy": "2024-04-10T20:05:45.076734Z", + "iopub.status.idle": "2024-04-10T20:05:45.080445Z", + "shell.execute_reply": "2024-04-10T20:05:45.079808Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.077053Z" + } + }, "outputs": [], "source": [ "barcode_seqs = [(seq, minq_char * len(seq)) for seq in barcode_seqs]" @@ -475,7 +574,15 @@ { "cell_type": "code", "execution_count": 14, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.081577Z", + "iopub.status.busy": "2024-04-10T20:05:45.081245Z", + "iopub.status.idle": "2024-04-10T20:05:45.085347Z", + "shell.execute_reply": "2024-04-10T20:05:45.084804Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.081550Z" + } + }, "outputs": [], "source": [ "lowq_char = chr(minq + 33 - 1) # low-quality Q-score\n", @@ -495,7 +602,15 @@ { "cell_type": "code", "execution_count": 15, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.086445Z", + "iopub.status.busy": "2024-04-10T20:05:45.086135Z", + "iopub.status.idle": "2024-04-10T20:05:45.090674Z", + "shell.execute_reply": "2024-04-10T20:05:45.089984Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.086419Z" + } + }, "outputs": [ { "name": "stdout", @@ -576,6 +691,13 @@ "classes": [], "id": "", "n": "13" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.091953Z", + "iopub.status.busy": "2024-04-10T20:05:45.091602Z", + "iopub.status.idle": "2024-04-10T20:05:45.098706Z", + "shell.execute_reply": "2024-04-10T20:05:45.097642Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.091921Z" } }, "outputs": [], @@ -602,7 +724,15 @@ { "cell_type": "code", "execution_count": 17, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.100991Z", + "iopub.status.busy": "2024-04-10T20:05:45.100290Z", + "iopub.status.idle": "2024-04-10T20:05:45.113899Z", + "shell.execute_reply": "2024-04-10T20:05:45.113239Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.100933Z" + } + }, "outputs": [], "source": [ "with tempfile.NamedTemporaryFile(\"r+\") as fastq:\n", @@ -624,7 +754,15 @@ { "cell_type": "code", "execution_count": 18, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.115209Z", + "iopub.status.busy": "2024-04-10T20:05:45.114844Z", + "iopub.status.idle": "2024-04-10T20:05:45.123314Z", + "shell.execute_reply": "2024-04-10T20:05:45.122677Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.115178Z" + } + }, "outputs": [ { "data": { @@ -705,7 +843,15 @@ { "cell_type": "code", "execution_count": 19, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.124438Z", + "iopub.status.busy": "2024-04-10T20:05:45.124130Z", + "iopub.status.idle": "2024-04-10T20:05:45.132350Z", + "shell.execute_reply": "2024-04-10T20:05:45.131799Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.124412Z" + } + }, "outputs": [ { "data": { @@ -770,6 +916,13 @@ " lib_1\n", " sample_1\n", " \n", + " \n", + " 5\n", + " read too short\n", + " 0\n", + " lib_1\n", + " sample_1\n", + " \n", " \n", "\n", "" @@ -780,7 +933,8 @@ "1 invalid barcode 3 lib_1 sample_1\n", "2 unparseable barcode 2 lib_1 sample_1\n", "3 low quality barcode 1 lib_1 sample_1\n", - "4 failed chastity filter 0 lib_1 sample_1" + "4 failed chastity filter 0 lib_1 sample_1\n", + "5 read too short 0 lib_1 sample_1" ] }, "execution_count": 19, @@ -803,7 +957,15 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.133441Z", + "iopub.status.busy": "2024-04-10T20:05:45.133143Z", + "iopub.status.idle": "2024-04-10T20:05:45.155925Z", + "shell.execute_reply": "2024-04-10T20:05:45.155393Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.133416Z" + } + }, "outputs": [ { "name": "stdout", @@ -929,6 +1091,13 @@ "classes": [], "id": "", "n": "14" + }, + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.157017Z", + "iopub.status.busy": "2024-04-10T20:05:45.156703Z", + "iopub.status.idle": "2024-04-10T20:05:45.163082Z", + "shell.execute_reply": "2024-04-10T20:05:45.162517Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.156993Z" } }, "outputs": [], @@ -955,7 +1124,15 @@ { "cell_type": "code", "execution_count": 22, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.164156Z", + "iopub.status.busy": "2024-04-10T20:05:45.163844Z", + "iopub.status.idle": "2024-04-10T20:05:45.171713Z", + "shell.execute_reply": "2024-04-10T20:05:45.170643Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.164133Z" + } + }, "outputs": [], "source": [ "pd.testing.assert_frame_equal(\n", @@ -967,6 +1144,7 @@ " (\"unparseable barcode\", n_unparseable),\n", " (\"low quality barcode\", n_low_quality),\n", " (\"failed chastity filter\", 0),\n", + " (\"read too short\", 0),\n", " ],\n", " columns=[\"fate\", \"count\"],\n", " ),\n", @@ -984,17 +1162,28 @@ { "cell_type": "code", "execution_count": 23, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T20:05:45.173799Z", + "iopub.status.busy": "2024-04-10T20:05:45.173196Z", + "iopub.status.idle": "2024-04-10T20:05:49.443413Z", + "shell.execute_reply": "2024-04-10T20:05:49.442570Z", + "shell.execute_reply.started": "2024-04-10T20:05:45.173754Z" + } + }, "outputs": [ { "data": { - "image/png": "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gG7As+U+vnOu/dZee23mzp0LhDtxucu3xYsXs3DhwnYde5mSkpktljQF6AG078KxgKRBhCTUFZgL7GtmrxX50M4tXbN2LzoaV2Gsjz/+eKRIWjd06NClf5Dr8ELBj6U78cQTufjii7n44otZfvnlWbRoEYsXL+b6669no402alcMpdx9OxW4WNKxZvZKu756U68DmwOrAPsDN0raqUhiWtTQ0NC52AGmP13GaMqkoaGhyetUk1JhnK4+zZ8/v02LHy+66CJmzZrF0KFDWW211fjyyy/ZaqutWGGFFbj66qvbFUMpSekmQomS8ZIWAF/kv2lmq5cSiJktIFwaArwgaStCAbmjSzmec65yDjnkkCavu3TpQu/evdlqq61YccX2VTAqJSmd0K6v2HadgK9V6Ws555bBj3/844odu5QqATeWOwhJFwD3E8rprgQcBOwMDCv313LOpa3kFktltibhsrAXofnABGCYmT0cNSrnXFEbbbRRq5PikyZNKvnYSSQlMzs8dgzOuba74oormrxeuHAhkydP5o477uDYY49t17GTSErOudqy6667NhsbNmwY/fv356677uIHP/hBycdu0zYTSZtKKqkgnHOufmy44Yb861//atcx2nqmNI4w3zND0hvAVmY2s11f2TlXs957r2lBEDNj5syZXHvttfTu3btdx25rUvoU6EuombQ+JZbRdc51DLvtthtmhqQmE97rrLMOl156abuO3dakdAfwpKTphHIlYyUtKvaBZvaNdkXknEveXXc1rfO4cOFCpkyZwj333MPqq5e0fnqJNiUlMztK0p3ABsBo4BpgTru+snOuZm244YbNxgYOHMhaa63FGWecwc0331zysdt8983MHgCQNBgYZWaelJxzTay99tq88kr7tsSWsqL7J7nnktbNxt5tVxTOuZry3HPPNXmdm+i+6aabGDBgQLuOvcxJKVsacCbwK7JqIZLmAJcC52cNKp1zHdghhxyyZKI752tf+xpbb701v/71r9t17FIWT54PHE4oYZIrFrIDcA6hFtIZ7YrIOZe8559/vslrSXTr1q0sxy4lKR0CHGFm9+SNTZD0HnAVnpSc6/C6d69cScVSktLqhMYBhSZl7znnOqDC/W6tOe6440r+OqUkpfHAcYTmAU3iyN5zznVAjz76aJPXb731Fl999RW9evUCYPr06XTp0oWv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\n", + "image/png": "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lLgzNCGEEEKIopRKYGS7PP/3339yx3v27AnOOf744w+cOnVKPL5z504sWrQIjDG0b99eBeESQgghhCiZwHTv3h2cc+zduxe5ubnicdl6MG/fvoWvry+qV68Oc3NzDB06FBkZGRAEAV9//bXKgyeEEEKIflIqgfH09MSsWbPg7++PuLg48bi9vT127dqFKlWqgHOOly9fIjU1FZxzGBkZYc2aNXB3d1d58IQQQgjRT0otZMcYw6xZswo9161bN0RGRmL37t24desWcnJy4OjoCD8/P9ja2qok2KJ8++23mDdvnvjnU6dOwdPTU633JIQQQoh0yrwb9buqVq2KCRMmqPKSJQoLC8Off/6p0XsSQggh+io9PR1r164FALi7u6NVq1YFyuTk5ODq1at48eIFqlWrBldXVxgaGqo0DpUmMJqWl5eH8ePHIycnB9bW1khISJA6JEIIIUSnXbhwAcuWLQNjDL179y5wPioqCh9//DEeP34sHqtevToWLlxYaLJTWkqNgSnMkydPEBoairNnzyI9PV0VMSls8eLFCAkJQaNGjRAQEKDRexNCCCH66OLFiwCAli1bwt7eXu4c5xxTpkzB48ePwRgTX4mJifj4449V2tFQqgQmJSUFM2bMQO3atVGnTh20adMGXl5eiI6Oliu3fft2+Pn5Ydy4cSoJ9l2xsbGYMWMGAGDlypUq75oihBBCSEG3b98G57zQsaYnT54UF7WdPn06QkNDsXLlSpiamuLt27cIDAxUWRxKJzCRkZFwdXXFL7/8gri4OHDOwTkvtKy7uzv27t2LdevW4fz582UO9l2TJ0/G27dvMWrUKHTq1Eml1yaEEEJI4WS9KLLFbd8lWwvO2dkZH330EUxNTdGpUycMGzYMjDGx90YVlEpgMjIy0KNHD0RFRcHExATffPMNgoKCiixft25deHl5AQAOHDhQtkjfsXPnTgQFBcHKygrz589X2XUJIYQQUrykpCQAgJWVVYFzISEh4Jzjww8/lDvu5uYGIP/piaooNYh3xYoVePDgAUxNTXHu3Dm0aNGixDrdunXDiRMncOnSpdLGKCc5ORlTpkwBAPz++++oVq2aSq5LCCGEEMW9uy8ikL/noSxBeX+wrmzfxPfrlIVSPTB79+4FYwxTpkxRKHkBgObNmwPIf/SkCt988w2ePXuG9u3b08BdQgghRMNkHQcx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", "text/plain": [ "
" ] }, "metadata": { - "needs_background": "light" + "image/png": { + "height": 308, + "width": 280 + } }, "output_type": "display_data" } @@ -1016,7 +1205,7 @@ " + geom_bar(stat=\"identity\")\n", " + facet_grid(\"sample ~ library\")\n", " + facet_grid(\"sample ~ library\")\n", - " + scale_fill_manual(CBPALETTE, guide=False)\n", + " + scale_fill_manual(CBPALETTE)\n", " + theme(\n", " figure_size=(\n", " 1.4 * (1 + len(fates[\"library\"].unique())),\n", @@ -1050,7 +1239,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.11.7" }, "toc": { "nav_menu": {}, diff --git a/tests/count_codonvariant_files/fates.csv b/tests/count_codonvariant_files/fates.csv index 501ead0..5b030ee 100644 --- a/tests/count_codonvariant_files/fates.csv +++ b/tests/count_codonvariant_files/fates.csv @@ -3,14 +3,17 @@ invalid barcode,1739,library-1,plasmid,run-1 low quality barcode,480,library-1,plasmid,run-1 unparseable barcode,281,library-1,plasmid,run-1 failed chastity filter,0,library-1,plasmid,run-1 +read too short,0,library-1,plasmid,run-1 valid barcode,0,library-1,plasmid,run-1 invalid barcode,1761,library-1,uninduced,run-1 low quality barcode,374,library-1,uninduced,run-1 unparseable barcode,362,library-1,uninduced,run-1 valid barcode,3,library-1,uninduced,run-1 failed chastity filter,0,library-1,uninduced,run-1 +read too short,0,library-1,uninduced,run-1 invalid barcode,1844,library-2,plasmid,run-1 low quality barcode,435,library-2,plasmid,run-1 unparseable barcode,220,library-2,plasmid,run-1 valid barcode,1,library-2,plasmid,run-1 failed chastity filter,0,library-2,plasmid,run-1 +read too short,0,library-2,plasmid,run-1 diff --git a/tests/illuminabarcodeparser_toy_example.ipynb b/tests/illuminabarcodeparser_toy_example.ipynb index f077c54..c51037d 100644 --- a/tests/illuminabarcodeparser_toy_example.ipynb +++ b/tests/illuminabarcodeparser_toy_example.ipynb @@ -15,7 +15,15 @@ { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:22.648068Z", + "iopub.status.busy": "2024-04-10T19:51:22.647666Z", + "iopub.status.idle": "2024-04-10T19:51:23.690513Z", + "shell.execute_reply": "2024-04-10T19:51:23.689696Z", + "shell.execute_reply.started": "2024-04-10T19:51:22.648033Z" + } + }, "outputs": [], "source": [ "import tempfile\n", @@ -35,7 +43,15 @@ { "cell_type": "code", "execution_count": 2, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.695972Z", + "iopub.status.busy": "2024-04-10T19:51:23.695581Z", + "iopub.status.idle": "2024-04-10T19:51:23.702713Z", + "shell.execute_reply": "2024-04-10T19:51:23.701795Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.695935Z" + } + }, "outputs": [], "source": [ "parser = IlluminaBarcodeParser(bclen=4, upstream=\"ACATGA\", downstream=\"GACT\")" @@ -54,7 +70,15 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.708338Z", + "iopub.status.busy": "2024-04-10T19:51:23.707670Z", + "iopub.status.idle": "2024-04-10T19:51:23.726018Z", + "shell.execute_reply": "2024-04-10T19:51:23.725068Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.708272Z" + } + }, "outputs": [], "source": [ "r1file = tempfile.NamedTemporaryFile(mode=\"w\")\n", @@ -163,23 +187,32 @@ { "cell_type": "code", "execution_count": 4, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.729694Z", + "iopub.status.busy": "2024-04-10T19:51:23.729427Z", + "iopub.status.idle": "2024-04-10T19:51:23.744681Z", + "shell.execute_reply": "2024-04-10T19:51:23.743646Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.729664Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " barcode count\n", - "0 CGTA 2\n", - "1 AGTA 1\n", + "0 AGTA 1\n", + "1 CGTA 1\n", "2 GCCG 1\n", " fate count\n", - "0 valid barcode 4\n", - "1 unparseable barcode 3\n", + "0 unparseable barcode 3\n", + "1 valid barcode 3\n", "2 R1 / R2 disagree 1\n", "3 low quality barcode 1\n", - "4 failed chastity filter 0\n", - "5 invalid barcode 0\n" + "4 read too short 1\n", + "5 failed chastity filter 0\n", + "6 invalid barcode 0\n" ] } ], @@ -200,22 +233,31 @@ { "cell_type": "code", "execution_count": 5, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.748395Z", + "iopub.status.busy": "2024-04-10T19:51:23.748172Z", + "iopub.status.idle": "2024-04-10T19:51:23.759268Z", + "shell.execute_reply": "2024-04-10T19:51:23.758404Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.748370Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " barcode count\n", - "0 CGTA 2\n", - "1 AAGT 1\n", + "0 AAGT 1\n", + "1 CGTA 1\n", "2 GCCG 1\n", " fate count\n", - "0 valid barcode 4\n", - "1 unparseable barcode 3\n", + "0 unparseable barcode 3\n", + "1 valid barcode 3\n", "2 low quality barcode 2\n", - "3 failed chastity filter 0\n", - "4 invalid barcode 0\n" + "3 read too short 1\n", + "4 failed chastity filter 0\n", + "5 invalid barcode 0\n" ] } ], @@ -235,22 +277,31 @@ { "cell_type": "code", "execution_count": 6, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.763562Z", + "iopub.status.busy": "2024-04-10T19:51:23.763160Z", + "iopub.status.idle": "2024-04-10T19:51:23.777870Z", + "shell.execute_reply": "2024-04-10T19:51:23.776948Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.763528Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " barcode count library sample\n", - "0 CGTA 2 lib-1 s1\n", - "1 AAGT 1 lib-1 s1\n", + "0 AAGT 1 lib-1 s1\n", + "1 CGTA 1 lib-1 s1\n", "2 GCCG 1 lib-1 s1\n", " fate count library sample\n", - "0 valid barcode 4 lib-1 s1\n", - "1 unparseable barcode 3 lib-1 s1\n", + "0 unparseable barcode 3 lib-1 s1\n", + "1 valid barcode 3 lib-1 s1\n", "2 low quality barcode 2 lib-1 s1\n", - "3 failed chastity filter 0 lib-1 s1\n", - "4 invalid barcode 0 lib-1 s1\n" + "3 read too short 1 lib-1 s1\n", + "4 failed chastity filter 0 lib-1 s1\n", + "5 invalid barcode 0 lib-1 s1\n" ] } ], @@ -272,24 +323,33 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.779178Z", + "iopub.status.busy": "2024-04-10T19:51:23.778863Z", + "iopub.status.idle": "2024-04-10T19:51:23.792937Z", + "shell.execute_reply": "2024-04-10T19:51:23.791547Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.779151Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " barcode count\n", - "0 CGTA 2\n", - "1 AGTA 1\n", + "0 AGTA 1\n", + "1 CGTA 1\n", "2 GCCG 1\n", "3 GGAG 1\n", " fate count\n", - "0 valid barcode 5\n", + "0 valid barcode 4\n", "1 unparseable barcode 2\n", "2 R1 / R2 disagree 1\n", "3 low quality barcode 1\n", - "4 failed chastity filter 0\n", - "5 invalid barcode 0\n" + "4 read too short 1\n", + "5 failed chastity filter 0\n", + "6 invalid barcode 0\n" ] } ], @@ -318,23 +378,32 @@ { "cell_type": "code", "execution_count": 8, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.795621Z", + "iopub.status.busy": "2024-04-10T19:51:23.794665Z", + "iopub.status.idle": "2024-04-10T19:51:23.811820Z", + "shell.execute_reply": "2024-04-10T19:51:23.811230Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.795555Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " barcode count\n", - "0 CGTA 2\n", - "1 AGTA 1\n", + "0 AGTA 1\n", + "1 CGTA 1\n", "2 TAAT 0\n", " fate count\n", "0 unparseable barcode 3\n", - "1 valid barcode 3\n", + "1 valid barcode 2\n", "2 R1 / R2 disagree 1\n", "3 invalid barcode 1\n", "4 low quality barcode 1\n", - "5 failed chastity filter 0\n" + "5 read too short 1\n", + "6 failed chastity filter 0\n" ] } ], @@ -357,7 +426,15 @@ { "cell_type": "code", "execution_count": 9, - "metadata": {}, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T19:51:23.813291Z", + "iopub.status.busy": "2024-04-10T19:51:23.812924Z", + "iopub.status.idle": "2024-04-10T19:51:23.816757Z", + "shell.execute_reply": "2024-04-10T19:51:23.815995Z", + "shell.execute_reply.started": "2024-04-10T19:51:23.813264Z" + } + }, "outputs": [], "source": [ "r1file.close()\n", @@ -367,7 +444,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -381,7 +458,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.11.7" }, "toc": { "base_numbering": 1, @@ -398,5 +475,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/tests/illuminabarcodeparser_toy_example_w_upstream2.ipynb b/tests/illuminabarcodeparser_toy_example_w_upstream2.ipynb new file mode 100644 index 0000000..6af345b --- /dev/null +++ b/tests/illuminabarcodeparser_toy_example_w_upstream2.ipynb @@ -0,0 +1,393 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Toy example with `IlluminaBarcodeParser` containing an `upstream2` sequence\n", + "This example illustrates use of a [IlluminaBarcodeParser](https://jbloomlab.github.io/dms_variants/dms_variants.illuminabarcodeparser.html#dms_variants.illuminabarcodeparser.IlluminaBarcodeParser) on a toy example.\n", + "\n", + "It is written primarily as a test for that class.\n", + "\n", + "Import required modules:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:38.979735Z", + "iopub.status.busy": "2024-04-10T22:17:38.979371Z", + "iopub.status.idle": "2024-04-10T22:17:39.999532Z", + "shell.execute_reply": "2024-04-10T22:17:39.998756Z", + "shell.execute_reply.started": "2024-04-10T22:17:38.979703Z" + } + }, + "outputs": [], + "source": [ + "import tempfile\n", + "\n", + "from dms_variants.illuminabarcodeparser import IlluminaBarcodeParser" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Initialize an `IlluminaBarcodeParser` for a barcode arrangement that looks like this:\n", + "\n", + " 5'-[R2 binding site]-GCA-ACATGA-NNNN-[R1 binding site]-3'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.003968Z", + "iopub.status.busy": "2024-04-10T22:17:40.003644Z", + "iopub.status.idle": "2024-04-10T22:17:40.011300Z", + "shell.execute_reply": "2024-04-10T22:17:40.010467Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.003937Z" + } + }, + "outputs": [], + "source": [ + "parser = IlluminaBarcodeParser(bclen=4, upstream=\"ACATGA\", upstream2=\"GCA\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create temporary file holding the FASTQ reads.\n", + "We write some valid test reads and some invalid reads. \n", + "The header for each read explains why it is valid / invalid. \n", + "We use quality scores of ``?`` (30) or ``+`` (10) for high- and low-quality bases:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.015148Z", + "iopub.status.busy": "2024-04-10T22:17:40.014722Z", + "iopub.status.idle": "2024-04-10T22:17:40.022961Z", + "shell.execute_reply": "2024-04-10T22:17:40.022166Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.015118Z" + } + }, + "outputs": [], + "source": [ + "r1file = tempfile.NamedTemporaryFile(mode=\"w\")\n", + "\n", + "# valid TACG barcode, full flanking regions\n", + "_ = r1file.write(\"@valid_CGTA_barcode\\n\" \"CGTATCATGTTGC\\n\" \"+\\n\" \"?????????????\\n\")\n", + "\n", + "# valid CGTA barcode, partial flanking regions\n", + "_ = r1file.write(\n", + " \"@valid_CGTA_barcode_partial_flanking_region\\n\"\n", + " \"CGTATCATTGC\\n\"\n", + " \"+\\n\"\n", + " \"???????????\\n\"\n", + ")\n", + "\n", + "# valid GCCG barcode, extended flanking regions\n", + "_ = r1file.write(\n", + " \"@valid_GCCG_barcode_extended_flanking_region\\n\"\n", + " \"GCCGTCATGTTGCCAA\\n\"\n", + " \"+\\n\"\n", + " \"????????????????\\n\"\n", + ")\n", + "\n", + "# some sites low quality\n", + "_ = r1file.write(\"@low_quality_site\\n\" \"CGTATCATGTTGC\\n\" \"+\\n\" \"???+?????????\\n\")\n", + "\n", + "# N in barcode\n", + "_ = r1file.write(\"@N_in_barcode\\n\" \"CGTNTCATGTTGC\\n\" \"+\\n\" \"?????????????\\n\")\n", + "\n", + "# GGAG barcode, one mismatch in flanking region\n", + "_ = r1file.write(\n", + " \"@GGAG_barcode_one_mismatch_in_upstream\\n\" \"GGAGTCATGATGC\\n\" \"+\\n\" \"?????????????\\n\"\n", + ")\n", + "\n", + "# GGTG barcode, mismatch in both upstream regions\n", + "_ = r1file.write(\n", + " \"@GGTG_barcode_two_mismatch_in_upstream_and_upstream2\\n\"\n", + " \"GGTGTCATGATGG\\n\"\n", + " \"+\\n\"\n", + " \"?????????????\\n\"\n", + ")\n", + "\n", + "r1file.flush()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Parse the barcodes using both R1 and R2 reads:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.026647Z", + "iopub.status.busy": "2024-04-10T22:17:40.026403Z", + "iopub.status.idle": "2024-04-10T22:17:40.039583Z", + "shell.execute_reply": "2024-04-10T22:17:40.038894Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.026620Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " barcode count\n", + "0 CGTA 1\n", + "1 GCCG 1\n", + " fate count\n", + "0 unparseable barcode 3\n", + "1 valid barcode 2\n", + "2 low quality barcode 1\n", + "3 read too short 1\n", + "4 failed chastity filter 0\n", + "5 invalid barcode 0\n" + ] + } + ], + "source": [ + "barcodes, fates = parser.parse(r1file.name)\n", + "print(barcodes)\n", + "print(fates)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a parser that allows mismatch in `upstream`, and check that we recover barcode:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.042962Z", + "iopub.status.busy": "2024-04-10T22:17:40.042642Z", + "iopub.status.idle": "2024-04-10T22:17:40.056823Z", + "shell.execute_reply": "2024-04-10T22:17:40.056209Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.042936Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " barcode count\n", + "0 CGTA 1\n", + "1 GCCG 1\n", + "2 GGAG 1\n", + " fate count\n", + "0 valid barcode 3\n", + "1 unparseable barcode 2\n", + "2 low quality barcode 1\n", + "3 read too short 1\n", + "4 failed chastity filter 0\n", + "5 invalid barcode 0\n" + ] + } + ], + "source": [ + "parser_mismatch = IlluminaBarcodeParser(\n", + " bclen=4,\n", + " upstream=\"ACATGA\",\n", + " upstream2=\"GCA\",\n", + " upstream_mismatch=1,\n", + ")\n", + "barcodes_mismatch, fates_mismatch = parser_mismatch.parse(r1file.name)\n", + "print(barcodes_mismatch)\n", + "print(fates_mismatch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now classify outer flank failures differently from unparseable barcodes:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.058324Z", + "iopub.status.busy": "2024-04-10T22:17:40.057954Z", + "iopub.status.idle": "2024-04-10T22:17:40.069187Z", + "shell.execute_reply": "2024-04-10T22:17:40.068353Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.058295Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " barcode count\n", + "0 CGTA 1\n", + "1 GCCG 1\n", + "2 GGAG 1\n", + " fate count\n", + "0 valid barcode 3\n", + "1 invalid outer flank 1\n", + "2 low quality barcode 1\n", + "3 read too short 1\n", + "4 unparseable barcode 1\n", + "5 failed chastity filter 0\n", + "6 invalid barcode 0\n" + ] + } + ], + "source": [ + "parser_mismatch = IlluminaBarcodeParser(\n", + " bclen=4,\n", + " upstream=\"ACATGA\",\n", + " upstream2=\"GCA\",\n", + " upstream_mismatch=1,\n", + ")\n", + "barcodes_mismatch, fates_mismatch = parser_mismatch.parse(\n", + " r1file.name, outer_flank_fates=True\n", + ")\n", + "print(barcodes_mismatch)\n", + "print(fates_mismatch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a parser that allows mismatch in `upstream` and `upstream2`, and check that we recover barcode:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.070486Z", + "iopub.status.busy": "2024-04-10T22:17:40.070109Z", + "iopub.status.idle": "2024-04-10T22:17:40.082614Z", + "shell.execute_reply": "2024-04-10T22:17:40.081961Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.070458Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " barcode count\n", + "0 CGTA 1\n", + "1 GCCG 1\n", + "2 GGAG 1\n", + "3 GGTG 1\n", + " fate count\n", + "0 valid barcode 4\n", + "1 low quality barcode 1\n", + "2 read too short 1\n", + "3 unparseable barcode 1\n", + "4 failed chastity filter 0\n", + "5 invalid barcode 0\n" + ] + } + ], + "source": [ + "parser_mismatch = IlluminaBarcodeParser(\n", + " bclen=4,\n", + " upstream=\"ACATGA\",\n", + " upstream2=\"GCA\",\n", + " upstream_mismatch=1,\n", + " upstream2_mismatch=1,\n", + ")\n", + "barcodes_mismatch, fates_mismatch = parser_mismatch.parse(r1file.name)\n", + "print(barcodes_mismatch)\n", + "print(fates_mismatch)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Close the temporary file:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "execution": { + "iopub.execute_input": "2024-04-10T22:17:40.083879Z", + "iopub.status.busy": "2024-04-10T22:17:40.083467Z", + "iopub.status.idle": "2024-04-10T22:17:40.087525Z", + "shell.execute_reply": "2024-04-10T22:17:40.086863Z", + "shell.execute_reply.started": "2024-04-10T22:17:40.083850Z" + } + }, + "outputs": [], + "source": [ + "r1file.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/tests/monotonicsplineepistasisbottlenecklikelihood_model.ipynb b/tests/monotonicsplineepistasisbottlenecklikelihood_model.ipynb index eb6b40d..1150b2c 100644 --- a/tests/monotonicsplineepistasisbottlenecklikelihood_model.ipynb +++ b/tests/monotonicsplineepistasisbottlenecklikelihood_model.ipynb @@ -490,7 +490,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw()" ] diff --git a/tests/monotonicsplineepistasiscauchylikelihood_model.ipynb b/tests/monotonicsplineepistasiscauchylikelihood_model.ipynb index 5b962c2..53b625d 100644 --- a/tests/monotonicsplineepistasiscauchylikelihood_model.ipynb +++ b/tests/monotonicsplineepistasiscauchylikelihood_model.ipynb @@ -745,7 +745,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw()" ] diff --git a/tests/monotonicsplineepistasisgaussianlikelihood_model.ipynb b/tests/monotonicsplineepistasisgaussianlikelihood_model.ipynb index e9206c9..ddf217b 100644 --- a/tests/monotonicsplineepistasisgaussianlikelihood_model.ipynb +++ b/tests/monotonicsplineepistasisgaussianlikelihood_model.ipynb @@ -605,7 +605,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw()" ] diff --git a/tests/noepistasisbottlenecklikelihood_model.ipynb b/tests/noepistasisbottlenecklikelihood_model.ipynb index 01ab9ee..35c0108 100644 --- a/tests/noepistasisbottlenecklikelihood_model.ipynb +++ b/tests/noepistasisbottlenecklikelihood_model.ipynb @@ -403,7 +403,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw()" ] diff --git a/tests/noepistasisgaussianlikelihood_model.ipynb b/tests/noepistasisgaussianlikelihood_model.ipynb index 402e350..02307d3 100644 --- a/tests/noepistasisgaussianlikelihood_model.ipynb +++ b/tests/noepistasisgaussianlikelihood_model.ipynb @@ -705,7 +705,7 @@ " axis_text_x=element_text(angle=90),\n", " panel_grid_major_x=element_blank(), # no vertical grid lines\n", " )\n", - " + scale_fill_manual(values=CBPALETTE[1:], guide=False)\n", + " + scale_fill_manual(values=CBPALETTE[1:])\n", ")\n", "_ = p.draw()" ] diff --git a/tests/test_count_codonvariants.py b/tests/test_count_codonvariants.py index 7d3defc..ba165e2 100644 --- a/tests/test_count_codonvariants.py +++ b/tests/test_count_codonvariants.py @@ -155,6 +155,7 @@ def test_count_codonvariants(self): ) fatesfile = os.path.join(indir, "fates.csv") + print(fates) assert_frame_equal(fates, pd.read_csv(fatesfile)) libs_to_analyze = ["library-1"]