import uuid
from flask import (
g,
render_template,
send_file,
request,
redirect,
)
from werkzeug.exceptions import Forbidden
import sqlalchemy as sql
from app.model.orm import (
Bioreplicate,
Community,
Experiment,
MeasurementContext,
Study,
StudyUser,
Submission,
)
from app.view.forms.experiment_export_form import ExperimentExportForm
from app.view.forms.comparative_chart_form import ComparativeChartForm
import app.model.lib.util as util
[docs]
def study_show_page(publicId):
study = _fetch_study_for_visitor(
publicId,
check_user_visibility=False,
sql_options=(
# Level 1:
sql.orm.selectinload(Study.experiments, Experiment.compartments),
sql.orm.selectinload(Study.experiments, Experiment.community),
sql.orm.selectinload(Study.experiments, Experiment.perturbations),
sql.orm.selectinload(Study.experiments, Experiment.bioreplicates),
# Level 2:
sql.orm.selectinload(Study.experiments, Experiment.community, Community.strains),
sql.orm.selectinload(Study.experiments, Experiment.bioreplicates, Bioreplicate.measurementContexts),
# Level 3:
sql.orm.selectinload(
Study.experiments,
Experiment.bioreplicates,
Bioreplicate.measurementContexts,
MeasurementContext.measurements,
),
sql.orm.selectinload(
Study.experiments,
Experiment.bioreplicates,
Bioreplicate.measurementContexts,
MeasurementContext.technique,
),
sql.orm.selectinload(
Study.experiments,
Experiment.bioreplicates,
Bioreplicate.measurementContexts,
MeasurementContext.modelingResults,
),
)
)
if study.visible_to_user(g.current_user):
return render_template("pages/studies/show.html", study=study)
else:
return render_template("pages/studies/show_unpublished.html", study=study)
[docs]
def study_manage_page(publicId):
study = _fetch_study_for_visitor(publicId)
if not study.manageable_by_user(g.current_user):
raise Forbidden()
return render_template("pages/studies/manage.html", study=study)
[docs]
def study_export_page(publicId):
study = _fetch_study_for_visitor(publicId)
return render_template(
"pages/studies/export.html",
study=study,
studyId=publicId,
)
[docs]
def study_export_preview_fragment(publicId):
# We only need the id here, but we call it to apply visibility checks:
_fetch_study_for_visitor(publicId)
csv_previews = []
export_form = ExperimentExportForm(g.db_session, request.args)
experiment_data = export_form.get_experiment_data()
for experiment, experiment_df in experiment_data.items():
csv = experiment_df[:5].to_csv(index=False, sep=export_form.csv_separator)
csv_previews.append(f"""
<h3>{experiment.name}.csv ({len(experiment_df)} rows)</h3>
<pre>{csv}</pre>
""")
return '\n'.join(csv_previews)
[docs]
def study_download_data_zip(publicId):
study = _fetch_study_for_visitor(publicId)
csv_data = []
export_form = ExperimentExportForm(g.db_session, request.args)
experiment_data = export_form.get_experiment_data()
for experiment, experiment_df in experiment_data.items():
csv_bytes = experiment_df.to_csv(index=False, sep=export_form.csv_separator)
csv_name = f"{experiment.name}.csv"
csv_data.append((csv_name, csv_bytes))
readme_text = render_template(
'pages/studies/export_readme.md',
study=study,
experiments=experiment_data.keys(),
)
csv_data.append(('README.md', readme_text.encode('utf-8')))
zip_file = util.createzip(csv_data)
return send_file(
zip_file,
as_attachment=True,
download_name=f"{publicId}.zip",
)
[docs]
def study_reset_action(publicId):
study = _fetch_study_for_visitor(publicId, check_user_visibility=False)
if study.ownerUuid != g.current_user.uuid:
raise Forbidden()
study_submissions = g.db_session.scalars(
sql.select(Submission)
.where(Submission.studyUniqueID == study.uuid)
).all()
study.uuid = str(uuid.uuid4())
g.db_session.add(study)
g.db_session.add(StudyUser(
user=g.current_user,
study=study,
))
for submission in study_submissions:
submission.studyUniqueID = study.uuid
g.db_session.add(submission)
g.db_session.commit()
return redirect(request.referrer)
[docs]
def study_visualize_page(publicId):
study = _fetch_study_for_visitor(
publicId,
sql_options=(
# Level 1:
sql.orm.selectinload(Study.experiments, Experiment.bioreplicates),
# Level 2:
sql.orm.selectinload(
Study.experiments,
Experiment.bioreplicates,
Bioreplicate.measurementContexts,
),
# Level 3:
sql.orm.selectinload(
Study.experiments,
Experiment.bioreplicates,
Bioreplicate.measurementContexts,
MeasurementContext.modelingResults,
),
)
)
left_axis_ids = util.parse_comma_separated_request_ids('l')
right_axis_ids = util.parse_comma_separated_request_ids('r')
left_axis_model_ids = util.parse_comma_separated_request_ids('lm')
right_axis_model_ids = util.parse_comma_separated_request_ids('rm')
chart_form = ComparativeChartForm(
g.db_session,
time_units=study.timeUnits,
left_axis_ids=left_axis_ids,
right_axis_ids=right_axis_ids,
left_axis_model_ids=left_axis_model_ids,
right_axis_model_ids=right_axis_model_ids,
)
return render_template(
"pages/studies/visualize.html",
study=study,
chart_form=chart_form,
)
[docs]
def study_history_page(publicId):
study = _fetch_study_for_visitor(publicId)
study_submissions = g.db_session.scalars(
sql.select(Submission)
.where(Submission.studyUniqueID == study.uuid)
.where(Submission.isPublished)
.order_by(
Submission.publishedAt.desc(),
Submission.updatedAt.desc(),
)
).all()
return render_template(
'pages/studies/history.html',
study=study,
study_submissions=study_submissions,
)
[docs]
def study_chart_fragment(publicId):
study = _fetch_study_for_visitor(publicId)
args = request.form.to_dict()
width = request.args.get('width', None)
chart_form = ComparativeChartForm(
g.db_session,
time_units=study.timeUnits,
show_std=args.get('showStd', None) is not None,
show_perturbations=args.get('showPerturbations', None) is not None,
)
chart = chart_form.build_chart(args, width)
return render_template(
'pages/studies/visualize/_chart.html',
chart_form=chart_form,
chart=chart,
study=study,
)
def _fetch_study_for_visitor(publicId, check_user_visibility=True, sql_options=None):
sql_options = sql_options or ()
study = g.db_session.scalars(
sql.select(Study)
.where(Study.publicId == publicId)
.options(*sql_options)
.limit(1)
).one()
if check_user_visibility and not study.visible_to_user(g.current_user):
raise Forbidden()
return study