Skip to content

Commit

Permalink
Tresholds (#99)
Browse files Browse the repository at this point in the history
* X0 and XXX in place. Waiting for XXY and XYY treshold equations.

* tresholds for XXY and XYY

* truncating report

* Library_nM

* unique colors mm

* batch commetn

* Update CHANGELOG.md

* Update fetal_fraction_sex.py

* Update CHANGELOG.md

* Update __init__.py
  • Loading branch information
mayabrandi committed Jul 9, 2021
1 parent 24ab085 commit 89674f2
Show file tree
Hide file tree
Showing 19 changed files with 502 additions and 264 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
@@ -1,11 +1,21 @@
# Change Log

This change log will document the notable changes to this project in this file and it is following [Semantic Versioning](https://semver.org/)
## [x.x.x]
### Added

### Fixed

## [x.x.x]
## [1.2.0]
### Added
- samples view
- thresholds to the XY-plot
- adding batch comment
- unique colors in xy-plot and increased marker size

### Fixed
- truncates the html report
- expands the XY-plot so no samples are hidden

## [1.1.0]

Expand Down
17 changes: 10 additions & 7 deletions statina/API/external/api/api_v1/endpoints/batches.py
Expand Up @@ -5,7 +5,7 @@
import statina.crud.find.plots.fetal_fraction_plot_data as get_fetal_fraction
from statina.adapter import StatinaAdapter
from statina.API.external.api.deps import get_current_user
from statina.API.external.constants import TRISOMI_TRESHOLDS
from statina.API.external.constants import TRISOMI_TRESHOLDS, COLORS
from statina.config import get_nipt_adapter, templates
from statina.crud.find import find
from statina.crud.find.plots.coverage_plot_data import (
Expand Down Expand Up @@ -151,6 +151,7 @@ def fetal_fraction_XY(

batch: Batch = find.batch(batch_id=batch_id, adapter=adapter)

cases = get_fetal_fraction.samples(adapter=adapter, batch_id=batch_id)
control: FetalFractionSamples = get_fetal_fraction.samples(
batch_id=batch_id, adapter=adapter, control_samples=True
)
Expand All @@ -165,8 +166,8 @@ def fetal_fraction_XY(
},
)

x_max = max(control.FFX) + 1
x_min = min(control.FFX) - 1
x_max = max(control.FFX + cases.FFX) + 1
x_min = min(control.FFX + cases.FFX) - 1

sex_thresholds = SexChromosomeThresholds(x_min=x_min, x_max=x_max)
return templates.TemplateResponse(
Expand All @@ -176,15 +177,16 @@ def fetal_fraction_XY(
"XY_fetal_fraction_y": sex_thresholds.XY_fetal_fraction_y(),
"XX_lower": sex_thresholds.XX_lower(),
"XX_upper": sex_thresholds.XX_upper(),
# "XY_lower": sex_thresholds.XY_lower(),
# "XY_upper": sex_thresholds.XY_upper(),
# "XXY": sex_thresholds.XXY(),
"XY_upper": sex_thresholds.XY_upper(),
"XY_lower": sex_thresholds.XY_lower(),
"XXY": sex_thresholds.XXY(),
},
request=request,
current_user=user,
colors=COLORS,
control=control,
abnormal=abnormal_dict,
cases=get_fetal_fraction.samples(adapter=adapter, batch_id=batch_id),
cases=cases,
max_x=x_max,
min_x=x_min,
batch=batch.dict(),
Expand All @@ -207,6 +209,7 @@ def fetal_fraction(
context=dict(
request=request,
current_user=user,
colors=COLORS,
control=get_fetal_fraction.samples(
adapter=adapter, batch_id=batch_id, control_samples=True
),
Expand Down
70 changes: 29 additions & 41 deletions statina/API/external/api/api_v1/endpoints/download.py
Expand Up @@ -5,33 +5,23 @@
from starlette.requests import Request
from starlette.responses import StreamingResponse

from statina.API.external.constants import TRISOMI_TRESHOLDS

from statina.API.external.constants import COLORS
from statina.adapter.plugin import StatinaAdapter
from statina.API.external.api.deps import get_current_user
from statina.config import get_nipt_adapter, templates
from statina.crud.find import find
from statina.crud.find.plots import fetal_fraction_plot_data as get_fetal_fraction
from statina.crud.find.plots.coverage_plot_data import (
get_scatter_data_for_coverage_plot,
get_box_data_for_coverage_plot,
)
from statina.crud.find.plots.zscore_plot_data import (
get_samples_for_samp_tris_plot,
get_normal_for_samp_tris_plot,
get_abnormal_for_samp_tris_plot,
)
from statina.models.server.plots.coverage import CoveragePlotSampleData
from statina.models.server.plots.fetal_fraction import (
FetalFractionSamples,
FetalFractionControlAbNormal,
)
from statina.models.server.plots.fetal_fraction_sex import SexChromosomeThresholds
from statina.models.server.sample import Sample
from zipfile import ZIP_DEFLATED, ZipFile
import io
from os import PathLike
from typing import Union, List, Dict
from statina.models.database import DataBaseSample, User
from typing import Union, List
from statina.models.database import DataBaseSample, User, Batch
from statina.parse.batch import validate_file_path

router = APIRouter()
Expand Down Expand Up @@ -96,23 +86,22 @@ def sample_download(
)


@router.get("/batches/{batch_id}/report/{coverage}/{file_name}")
@router.get("/batches/{batch_id}/report/{file_name}")
def report(
request: Request,
batch_id: str,
file_name: str,
coverage: str,
adapter: StatinaAdapter = Depends(get_nipt_adapter),
user: User = Depends(get_current_user),
):
"""Report view, collecting all tables and plots from one batch."""

db_samples: List[DataBaseSample] = find.batch_samples(batch_id=batch_id, adapter=adapter)
samples: List[Sample] = [Sample(**db_sample.dict()) for db_sample in db_samples]
scatter_data: Dict[str, CoveragePlotSampleData] = get_scatter_data_for_coverage_plot(samples)
box_data: Dict[int, List[float]] = get_box_data_for_coverage_plot(samples)
samples: List[DataBaseSample] = find.batch_samples(batch_id=batch_id, adapter=adapter)
batch: Batch = find.batch(batch_id=batch_id, adapter=adapter)

cases = get_fetal_fraction.samples(adapter=adapter, batch_id=batch_id)
control: FetalFractionSamples = get_fetal_fraction.samples(
adapter=adapter, batch_id=batch_id, control_samples=True
batch_id=batch_id, adapter=adapter, control_samples=True
)
abnormal: FetalFractionControlAbNormal = get_fetal_fraction.control_abnormal(adapter)
abnormal_dict = abnormal.dict(
Expand All @@ -125,35 +114,34 @@ def report(
},
)

x_max = max(control.FFX + cases.FFX) + 1
x_min = min(control.FFX + cases.FFX) - 1

sex_thresholds = SexChromosomeThresholds(x_min=x_min, x_max=x_max)

template = templates.get_template("batch/report.html")
output_from_parsed_template = template.render(
# common
request=request,
current_user=user,
batch=find.batch(batch_id=batch_id, adapter=adapter),
# Zscore
tris_thresholds=TRISOMI_TRESHOLDS,
chromosomes=["13", "18", "21"],
ncv_chrom_data=get_samples_for_samp_tris_plot(adapter, batch_id=batch_id).dict(
by_alias=True
),
normal_data=get_normal_for_samp_tris_plot(adapter).dict(by_alias=True),
abnormal_data=get_abnormal_for_samp_tris_plot(adapter),
# Fetal Fraction preface
control=control,
cases=get_fetal_fraction.samples(adapter=adapter, batch_id=batch_id),
# Fetal Fraction XY
sex_thresholds={
"XY_fetal_fraction_y": sex_thresholds.XY_fetal_fraction_y(),
"XX_lower": sex_thresholds.XX_lower(),
"XX_upper": sex_thresholds.XX_upper(),
"XY_upper": sex_thresholds.XY_upper(),
"XY_lower": sex_thresholds.XY_lower(),
"XXY": sex_thresholds.XXY(),
},
control=control,
abnormal=abnormal_dict,
max_x=max(control.FFX) + 1,
min_x=min(control.FFX) - 1,
cases=cases,
colors=COLORS,
max_x=x_max,
min_x=x_min,
# table
sample_info=samples,
# coverage
coverage=coverage,
x_axis=list(range(1, 23)),
scatter_data=scatter_data,
box_data=box_data,
page_id="batches",
sample_info=[Sample(**sample.dict()) for sample in samples],
)

in_mem_file = io.StringIO()
Expand Down
1 change: 1 addition & 0 deletions statina/API/external/api/api_v1/endpoints/statistics.py
Expand Up @@ -33,6 +33,7 @@ def statistics(
"GC_Dropout",
"AT_Dropout",
"Bin2BinVariance",
"Library_nM",
]

batches = get_last_batches(adapter=adapter, nr_of_batches=nr_batches)
Expand Down
24 changes: 23 additions & 1 deletion statina/API/external/api/api_v1/endpoints/update.py
Expand Up @@ -13,7 +13,7 @@
from statina.crud import update
from statina.crud.delete import delete_batches
from statina.crud.find import find
from statina.models.database import DataBaseSample, User
from statina.models.database import DataBaseSample, User, Batch

router = APIRouter()

Expand Down Expand Up @@ -85,6 +85,28 @@ async def set_sample_status(
return RedirectResponse(request.headers.get("referer"))


@router.post("/batch_comment")
async def batch_comment(
request: Request,
adapter: StatinaAdapter = Depends(get_nipt_adapter),
user: User = Depends(get_current_user),
):
"""Update batch comment"""

form = await request.form()

if user.role not in ["RW", "admin"]:
return RedirectResponse(request.headers.get("referer"))
batch_id: str = form["batch_id"]
batch: Batch = find.batch(batch_id=batch_id, adapter=adapter)
comment: str = form.get("comment")
if comment != batch.comment:
batch.comment = comment
update.update_batch(adapter=adapter, batch=batch)

return RedirectResponse(request.headers.get("referer"))


@router.post("/sample_comment")
async def sample_comment(
request: Request,
Expand Down
79 changes: 54 additions & 25 deletions statina/API/external/api/api_v1/templates/batch/header.html
Expand Up @@ -9,33 +9,62 @@
</div>
<div class="row">
<div class="col-lg-9"><big><em> Sequenced: {{ batch.SequencingDate }}</em></big></div>
<ul class="nav navbar-top-links navbar-right">
<li class="dropdown">
<button class="btn btn-secondary dropdown-toggle" data-toggle="dropdown">
Batch Downloads
</button>
<ul class="dropdown-menu">
<a class="dropdown-item" href="{{ url_for('report', batch_id=batch.batch_id , file_name=batch.batch_id+"_report.html", coverage=0) }}">
Report</a>
<li class="divider"></li>
<a class="dropdown-item" href="{{ url_for('report', batch_id=batch.batch_id , file_name=batch.batch_id+"_coverage_report.html", coverage=1) }}">
Coverage Report</a>
<li class="divider"></li>
<a class="dropdown-item"
href="{{ url_for('batch_download', file_id='multiqc_report', file_name='multiqc_report', batch_id=batch.batch_id) }}">Multi
QC</a>
<li class="divider"></li>
<a class="dropdown-item"
href="{{ url_for('batch_download', file_id='result_file', file_name='result_file',batch_id=batch.batch_id) }}">Fluffy
Result file</a>
<li class="divider"></li>
<a class="dropdown-item"
href="{{ url_for('batch_download', file_id='segmental_calls', file_name=batch.batch_id+'.zip', batch_id=batch.batch_id) }}">Full Batch Archive</a>
</ul>
</li>
</ul>
</div>
<br>
<div class="row">
<div class="col-lg-12">
{% if current_user.role in ['RW','admin'] %}
<form action="{{ url_for('batch_comment') }}" method="post">

<div class="form-group">
<textarea class="form-control" rows="2" name="comment">{{ batch.comment }}</textarea>
</div>
<td>
<input type=text name="form_id" value="set_batch_comment" hidden>
<input type=text name="batch_id" value="{{ batch.batch_id }}" hidden>
</td>
<td>
<p align="right">
<input type="submit" class="btn" value="Save comment">
</p>
</td>
</form>
{% else %}
<div class="panel panel-default">
<div class="panel-heading">Comment</div>
<div class="panel-body">{{ batch.comment }}</div>
</div>
{% endif %}
</div>
<div class="row">
<ul class="nav navbar-top-links navbar-right">
<li class="dropdown">
<button class="btn btn-secondary dropdown-toggle" data-toggle="dropdown">
Batch Downloads <i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu">
<a class="dropdown-item"
href="{{ url_for('report', batch_id=batch.batch_id , file_name=batch.batch_id+"_report.html") }}">
Report</a>
<li class="divider"></li>
<a class="dropdown-item"
href="{{ url_for('batch_download', file_id='multiqc_report', file_name='multiqc_report', batch_id=batch.batch_id) }}">Multi
QC</a>
<li class="divider"></li>
<a class="dropdown-item"
href="{{ url_for('batch_download', file_id='result_file', file_name='result_file',batch_id=batch.batch_id) }}">Fluffy
Result file</a>
<li class="divider"></li>
<a class="dropdown-item"
href="{{ url_for('batch_download', file_id='segmental_calls', file_name=batch.batch_id+'.zip', batch_id=batch.batch_id) }}">Full
Batch Archive</a>
</ul>
</li>
</ul>
</div>
</div>
</div> <!--jumbotron-->

<ul class="nav nav-tabs" id="myTab">
<li {% if page_id =='batches' %} class="active" {% endif %}><a
href="{{ url_for('batch', batch_id = batch.batch_id) }}">Batch Summary Table</a>
Expand Down

0 comments on commit 89674f2

Please sign in to comment.