diff options
| author | Frederick Muriuki Muriithi | 2025-12-29 11:56:58 -0600 |
|---|---|---|
| committer | Frederick Muriuki Muriithi | 2025-12-29 11:56:58 -0600 |
| commit | 3e50c29359da9cdd02ca585ae900ccb2e0f8668a (patch) | |
| tree | 2568edece571914d3473463b545f1f1ebe89cf35 | |
| parent | b40f14bb409d54fda957e2d8269f1bc86bd34e58 (diff) | |
| download | gn-uploader-3e50c29359da9cdd02ca585ae900ccb2e0f8668a.tar.gz | |
Phenotypes: Move feature to new UI templates.
18 files changed, 43 insertions, 1835 deletions
diff --git a/uploader/phenotypes/views.py b/uploader/phenotypes/views.py index 42f2e34..c4c6170 100644 --- a/uploader/phenotypes/views.py +++ b/uploader/phenotypes/views.py @@ -31,9 +31,6 @@ from flask import (flash, from r_qtl import r_qtl2_qc as rqc from r_qtl import exceptions as rqe - -from uploader.sui import sui_template - from uploader import jobs from uploader import session from uploader.files import save_file @@ -197,7 +194,7 @@ def view_dataset(# pylint: disable=[unused-argument] start_at = max(safe_int(request.args.get("start_at") or 0), 0) count = int(request.args.get("count") or 20) - return render_template(sui_template("phenotypes/view-dataset.html"), + return render_template("phenotypes/view-dataset.html", species=species, population=population, dataset=dataset, @@ -420,9 +417,9 @@ def add_phenotypes(species: dict, population: dict, dataset: dict, **kwargs):# p if request.method == "GET": today = datetime.date.today() return render_template( - sui_template("phenotypes/add-phenotypes-with-rqtl2-bundle.html" - if use_bundle - else "phenotypes/add-phenotypes-raw-files.html"), + ("phenotypes/add-phenotypes-with-rqtl2-bundle.html" + if use_bundle + else "phenotypes/add-phenotypes-raw-files.html"), species=species, population=population, dataset=dataset, @@ -509,7 +506,7 @@ def job_status( except jobs.JobNotFound as _jnf: job = None - return render_template(sui_template("phenotypes/job-status.html"), + return render_template("phenotypes/job-status.html", species=species, population=population, dataset=dataset, @@ -589,7 +586,7 @@ def review_job_data( for filetype,meta in metadata.items() } _job_metadata = json.loads(job["job-metadata"]) - return render_template(sui_template("phenotypes/review-job-data.html"), + return render_template("phenotypes/review-job-data.html", species=species, population=population, dataset=dataset, @@ -980,7 +977,7 @@ def load_data_success( (_publication["Title"] or "")) if item != "") return render_template( - sui_template("phenotypes/load-phenotypes-success.html"), + "phenotypes/load-phenotypes-success.html", species=species, population=population, dataset=dataset, diff --git a/uploader/templates/phenotypes/add-phenotypes-base.html b/uploader/templates/phenotypes/add-phenotypes-base.html index 9909c20..690c7e1 100644 --- a/uploader/templates/phenotypes/add-phenotypes-base.html +++ b/uploader/templates/phenotypes/add-phenotypes-base.html @@ -1,26 +1,13 @@ {%extends "phenotypes/base.html"%} {%from "flash_messages.html" import flash_all_messages%} {%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%} {%block title%}Phenotypes{%endblock%} {%block pagetitle%}Phenotypes{%endblock%} -{%block lvl4_breadcrumbs%} -<li {%if activelink=="add-phenotypes"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">Add Phenotypes</a> -</li> -{%endblock%} - {%block contents%} +{{super()}} {{flash_all_messages()}} <div class="row"> @@ -83,6 +70,8 @@ {%endblock%} + + {%block javascript%} <script type="text/javascript"> $(function() { diff --git a/uploader/templates/phenotypes/add-phenotypes-raw-files.html b/uploader/templates/phenotypes/add-phenotypes-raw-files.html index 67b56e3..a02fae7 100644 --- a/uploader/templates/phenotypes/add-phenotypes-raw-files.html +++ b/uploader/templates/phenotypes/add-phenotypes-raw-files.html @@ -1,7 +1,6 @@ {%extends "phenotypes/add-phenotypes-base.html"%} {%from "flash_messages.html" import flash_all_messages%} {%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%} {%from "phenotypes/macro-display-preview-table.html" import display_preview_table%} {%from "phenotypes/macro-display-resumable-elements.html" import display_resumable_elements%} @@ -9,19 +8,6 @@ {%block pagetitle%}Phenotypes{%endblock%} -{%block lvl4_breadcrumbs%} -<li {%if activelink=="add-phenotypes"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">Add Phenotypes</a> -</li> -{%endblock%} - {%block frm_add_phenotypes_documentation%} <p>This page will allow you to upload all the separate files that make up your phenotypes. Here, you will have to upload each separate file individually. If @@ -447,10 +433,6 @@ {%endblock%} -{%block sidebarcontents%} -{{display_pheno_dataset_card(species, population, dataset)}} -{%endblock%} - {%block more_javascript%} <script src="{{url_for('base.node_modules', diff --git a/uploader/templates/phenotypes/add-phenotypes-with-rqtl2-bundle.html b/uploader/templates/phenotypes/add-phenotypes-with-rqtl2-bundle.html index 898fc0c..4afd6ab 100644 --- a/uploader/templates/phenotypes/add-phenotypes-with-rqtl2-bundle.html +++ b/uploader/templates/phenotypes/add-phenotypes-with-rqtl2-bundle.html @@ -1,25 +1,11 @@ {%extends "phenotypes/add-phenotypes-base.html"%} {%from "flash_messages.html" import flash_all_messages%} {%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%} {%block title%}Phenotypes{%endblock%} {%block pagetitle%}Phenotypes{%endblock%} -{%block lvl4_breadcrumbs%} -<li {%if activelink=="add-phenotypes"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">Add Phenotypes</a> -</li> -{%endblock%} - {%block frm_add_phenotypes_documentation%} <p>Select the zip file bundle containing information on the phenotypes you wish to upload, then click the "Upload Phenotypes" button below to @@ -201,7 +187,3 @@ <em>phenotypes × individuals</em>.</p> </div> {%endblock%} - -{%block sidebarcontents%} -{{display_pheno_dataset_card(species, population, dataset)}} -{%endblock%} diff --git a/uploader/templates/phenotypes/base.html b/uploader/templates/phenotypes/base.html index adbc012..fe7ccd3 100644 --- a/uploader/templates/phenotypes/base.html +++ b/uploader/templates/phenotypes/base.html @@ -1,19 +1,25 @@ {%extends "populations/base.html"%} +{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_sui_pheno_dataset_card%} -{%block lvl3_breadcrumbs%} -<li {%if activelink=="phenotypes"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - {%if dataset is mapping%} +{%block breadcrumbs%} +{{super()}} +<li class="breadcrumb-item"> <a href="{{url_for('species.populations.phenotypes.view_dataset', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">{{dataset.Name}}</a> - {%else%} - <a href="{{url_for('species.populations.phenotypes.index')}}">Phenotypes</a> - {%endif%} + species_id=species['SpeciesId'], + population_id=population['Id'], + dataset_id=dataset['Id'])}}"> + {{dataset["Name"]}} + </a> </li> -{%block lvl4_breadcrumbs%}{%endblock%} +{%endblock%} + +{%block contents%} +<div class="row"> + <h2 class="heading">{{dataset.FullName}} ({{dataset.Name}})</h2> +</div> +{%endblock%} + + +{%block sidebarcontents%} +{{display_sui_pheno_dataset_card(species, population, dataset)}} {%endblock%} diff --git a/uploader/templates/phenotypes/job-status.html b/uploader/templates/phenotypes/job-status.html index 257f726..0bbe8e0 100644 --- a/uploader/templates/phenotypes/job-status.html +++ b/uploader/templates/phenotypes/job-status.html @@ -2,7 +2,6 @@ {%from "cli-output.html" import cli_output%} {%from "flash_messages.html" import flash_all_messages%} {%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%} {%block extrameta%} {%if job and job.status not in ("success", "completed:success", "error", "completed:error")%} @@ -14,23 +13,13 @@ {%block pagetitle%}Phenotypes{%endblock%} -{%block lvl4_breadcrumbs%} -<li {%if activelink=="add-phenotypes"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">View Datasets</a> -</li> -{%endblock%} - {%block contents%} {%if job%} -<h4 class="subheading">Progress</h4> +<div class="row"> + <h2 class="heading">{{dataset.FullName}} ({{dataset.Name}})</h2> + <h3 class="subheading">upload progress</h3> +</div> <div class="row" style="overflow:scroll;"> <p><strong>Process Status:</strong> {{job.status}}</p> {%if metadata%} @@ -80,7 +69,7 @@ {%endif%} </div> -<h4 class="subheading">Errors</h4> +<h3 class="subheading">upload errors</h3> <div class="row" style="max-height: 20em; overflow: scroll;"> {%if errors | length == 0 %} <p class="text-info"> @@ -149,7 +138,3 @@ </div> {%endif%} {%endblock%} - -{%block sidebarcontents%} -{{display_pheno_dataset_card(species, population, dataset)}} -{%endblock%} diff --git a/uploader/templates/phenotypes/load-phenotypes-success.html b/uploader/templates/phenotypes/load-phenotypes-success.html index 645be16..1fb0e61 100644 --- a/uploader/templates/phenotypes/load-phenotypes-success.html +++ b/uploader/templates/phenotypes/load-phenotypes-success.html @@ -1,26 +1,14 @@ {%extends "phenotypes/base.html"%} {%from "flash_messages.html" import flash_all_messages%} {%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%} {%block title%}Phenotypes{%endblock%} {%block pagetitle%}Phenotypes{%endblock%} -{%block lvl4_breadcrumbs%} -<li {%if activelink=="load-phenotypes-success"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">Add Phenotypes</a> -</li> -{%endblock%} - {%block contents%} +{{super()}} + <div class="row"> <p>You have successfully loaded <!-- maybe indicate the number of phenotypes here? -->your @@ -34,9 +22,5 @@ </div> {%endblock%} -{%block sidebarcontents%} -{{display_pheno_dataset_card(species, population, dataset)}} -{%endblock%} - {%block more_javascript%}{%endblock%} diff --git a/uploader/templates/phenotypes/review-job-data.html b/uploader/templates/phenotypes/review-job-data.html index 859df74..c8355b2 100644 --- a/uploader/templates/phenotypes/review-job-data.html +++ b/uploader/templates/phenotypes/review-job-data.html @@ -104,10 +104,6 @@ {%endif%} {%endblock%} -{%block sidebarcontents%} -{{display_pheno_dataset_card(species, population, dataset)}} -{%endblock%} - {%block javascript%} <script type="text/javascript"> diff --git a/uploader/templates/phenotypes/sui-add-phenotypes-base.html b/uploader/templates/phenotypes/sui-add-phenotypes-base.html deleted file mode 100644 index 1e71267..0000000 --- a/uploader/templates/phenotypes/sui-add-phenotypes-base.html +++ /dev/null @@ -1,155 +0,0 @@ -{%extends "phenotypes/sui-base.html"%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block contents%} -{{super()}} -{{flash_all_messages()}} - -<div class="row"> - <form id="frm-add-phenotypes" - method="POST" - enctype="multipart/form-data" - action="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id, - use_bundle=use_bundle)}}" - data-resumable-target="{{url_for('files.resumable_upload_post')}}"> - <legend>Add New Phenotypes</legend> - - <div class="form-text help-block"> - {%block frm_add_phenotypes_documentation%}{%endblock%} - <p><strong class="text-warning">This will not update any existing phenotypes!</strong></p> - </div> - - {%block frm_add_phenotypes_elements%}{%endblock%} - - <fieldset id="fldset-publication-info"> - <legend>Publication Information</legend> - <input type="hidden" name="publication-id" id="txt-publication-id" /> - <span class="form-text text-muted"> - Select a publication for your data. <br /> - Can't find a publication you can use? Go ahead and - <a href="{{url_for( - 'publications.create_publication', - return_to='species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">create a new publication</a>.</span> - <table id="tbl-select-publication" class="table compact stripe"> - <thead> - <tr> - <th>#</th> - <th>PubMed ID</th> - <th>Title</th> - <th>Authors</th> - </tr> - </thead> - - <tbody></tbody> - </table> - </fieldset> - - <div class="form-group"> - <input type="submit" - value="upload phenotypes" - class="btn btn-primary" /> - </div> - </form> -</div> - -<div class="row"> - {%block page_documentation%}{%endblock%} -</div> - -{%endblock%} - - - - -{%block javascript%} -<script type="text/javascript"> - $(function() { - var publicationsDataTable = buildDataTable( - "#tbl-select-publication", - [], - [ - {data: "index"}, - { - searchable: true, - data: (pub) => { - if(pub.PubMed_ID) { - return `<a href="https://pubmed.ncbi.nlm.nih.gov/` + - `${pub.PubMed_ID}/" target="_blank" ` + - `title="Link to publication on NCBI.">` + - `${pub.PubMed_ID}</a>`; - } - return ""; - } - }, - { - searchable: true, - data: (pub) => { - var title = "⸻"; - if(pub.Title) { - title = pub.Title - } - return `<a href="/publications/view/${pub.Id}" ` + - `target="_blank" ` + - `title="Link to view publication details">` + - `${title}</a>`; - } - }, - { - searchable: true, - data: (pub) => { - authors = pub.Authors.split(",").map( - (item) => {return item.trim();}); - if(authors.length > 1) { - return authors[0] + ", et. al."; - } - return authors[0]; - } - } - ], - { - serverSide: true, - ajax: { - url: "/publications/list", - dataSrc: "publications" - }, - select: "single", - paging: true, - scrollY: 700, - deferRender: true, - scroller: true, - scrollCollapse: true, - layout: { - topStart: "info", - topEnd: "search" - } - }); - publicationsDataTable.on("select", (event, datatable, type, indexes) => { - indexes.forEach((element, index, thearray) => { - let row = datatable.row(element).node(); - console.debug(datatable.row(element).data()); - $("#frm-add-phenotypes #txt-publication-id").val( - datatable.row(element).data().Id); - }); - }); - publicationsDataTable.on("deselect", (event, datatable, type, indexes) => { - indexes.forEach((element, index, thearray) => { - let row = datatable.row(element).node(); - $("#frm-add-phenotypes #txt-publication-id").val(null); - }); - }); - }); -</script> - -{%block more_javascript%}{%endblock%} -{%endblock%} diff --git a/uploader/templates/phenotypes/sui-add-phenotypes-raw-files.html b/uploader/templates/phenotypes/sui-add-phenotypes-raw-files.html deleted file mode 100644 index 6038617..0000000 --- a/uploader/templates/phenotypes/sui-add-phenotypes-raw-files.html +++ /dev/null @@ -1,829 +0,0 @@ -{%extends "phenotypes/sui-add-phenotypes-base.html"%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-preview-table.html" import display_preview_table%} -{%from "phenotypes/macro-display-resumable-elements.html" import display_resumable_elements%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block frm_add_phenotypes_documentation%} -<p>This page will allow you to upload all the separate files that make up your - phenotypes. Here, you will have to upload each separate file individually. If - you want instead to upload all your files as a single ZIP file, - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id, - use_bundle=true)}}" - title="">click here</a>.</p> -{%endblock%} - -{%block frm_add_phenotypes_elements%} -<fieldset id="fldset-file-metadata"> - <legend>File(s) Metadata</legend> - <div class="form-group"> - <label for="txt-file-separator" class="form-label">File Separator</label> - <div class="input-group"> - <input id="txt-file-separator" - name="file-separator" - type="text" - value="	" - class="form-control" - maxlength="1" /> - <span class="input-group-btn"> - <button id="btn-reset-file-separator" class="btn btn-info">Reset Default</button> - </span> - </div> - <span class="form-text text-muted"> - Provide the character that separates the fields in your file(s). It should - be the same character for all files (if more than one is provided).<br /> - A tab character will be assumed if you leave this field blank. See - <a href="#docs-file-separator" - title="Documentation for file-separator characters"> - documentation for more information</a>. - </span> - </div> - - <div class="form-group"> - <label for="txt-file-comment-character" class="form-label">File Comment-Character</label> - <div class="input-group"> - <input id="txt-file-comment-character" - name="file-comment-character" - type="text" - value="#" - class="form-control" - maxlength="1" /> - <span class="input-group-btn"> - <button id="btn-reset-file-comment-character" class="btn btn-info"> - Reset Default</button> - </span> - </div> - <span class="form-text text-muted"> - This specifies that lines that begin with the character provided will be - considered comment lines and ignored in their entirety. See - <a href="#docs-file-comment-character" - title="Documentation for comment characters"> - documentation for more information</a>. - </span> - </div> - - <div class="form-group"> - <label for="txt-file-na" class="form-label">File "No-Value" Indicators</label> - <div class="input-group"> - <input id="txt-file-na" - name="file-na" - type="text" - value="- NA N/A" - class="form-control" /> - <span class="input-group-btn"> - <button id="btn-reset-file-na" class="btn btn-info">Reset Default</button> - </span> - </div> - <span class="form-text text-muted"> - This specifies strings in your file indicate that there is no value for a - particular cell (a cell is where a column and row intersect). Provide a - space-separated list of strings if you have more than one way of - indicating no values. See - <a href="#docs-file-na" title="Documentation for no-value fields"> - documentation for more information</a>.</span> - </div> -</fieldset> - -<fieldset id="fldset-files"> - <legend>Data File(s)</legend> - - <fieldset id="fldset-descriptions-file"> - <div class="form-group"> - <div class="form-check"> - <input id="chk-phenotype-descriptions-transposed" - name="phenotype-descriptions-transposed" - type="checkbox" - class="form-check-input" - style="border: solid #8EABF0" /> - <label for="chk-phenotype-descriptions-transposed" - class="form-check-label"> - Description file transposed?</label> - </div> - - <div class="non-resumable-elements"> - <label for="finput-phenotype-descriptions" class="form-label"> - Phenotype Descriptions</label> - <input id="finput-phenotype-descriptions" - name="phenotype-descriptions" - class="form-control" - type="file" - data-preview-table="tbl-preview-pheno-desc" - required="required" /> - <span class="form-text text-muted"> - Provide a file that contains only the phenotype descriptions, - <a href="#docs-file-phenotype-description" - title="Documentation of the phenotype data file format."> - the documentation for the expected format of the file</a>.</span> - </div> - {{display_resumable_elements( - "resumable-phenotype-descriptions", - "phenotype descriptions", - '<p>Drag and drop the CSV file that contains the descriptions of your - phenotypes here.</p> - - <p>The CSV file should be a matrix of - <strong>phenotypes × descriptions</strong> i.e. The first column - contains the phenotype names/identifiers whereas the first row is a list - of metadata fields like, "description", "units", etc.</p> - - <p>If the format is transposed (i.e. - <strong>descriptions × phenotypes</strong>) select the checkbox above. - </p> - - <p>Please see the - <a href="#docs-file-phenotype-description" - title="Documentation of the phenotype data file format."> - "Phenotypes Descriptions" documentation</a> section below for more - information on the expected format of the file provided here.</p>')}} - {{display_preview_table( - "tbl-preview-pheno-desc", "phenotype descriptions")}} - </div> - </fieldset> - - - <fieldset id="fldset-data-file"> - <div class="form-group"> - <div class="form-check"> - <input id="chk-phenotype-data-transposed" - name="phenotype-data-transposed" - type="checkbox" - class="form-check-input" - style="border: solid #8EABF0" /> - <label for="chk-phenotype-data-transposed" class="form-check-label"> - Data file transposed?</label> - </div> - - <div class="non-resumable-elements"> - <label for="finput-phenotype-data" class="form-label">Phenotype Data</label> - <input id="finput-phenotype-data" - name="phenotype-data" - class="form-control" - type="file" - data-preview-table="tbl-preview-pheno-data" - required="required" /> - <span class="form-text text-muted"> - Provide a file that contains only the phenotype data. See - <a href="#docs-file-phenotype-data" - title="Documentation of the phenotype data file format."> - the documentation for the expected format of the file</a>.</span> - </div> - - {{display_resumable_elements( - "resumable-phenotype-data", - "phenotype data", - '<p>Drag and drop a CSV file that contains the phenotypes numerical data - here. You can click the "Browse" button (below and to the right) to - select the file from your computer.</p> - - <p>The CSV should be a matrix of <strong>samples × phenotypes</strong>, - i.e. The first column contains the samples identifiers while the first - row is the list of phenotypes identifiers occurring in the phenotypes - descriptions file.</p> - - <p>If the format is transposed (i.e <strong>phenotypes × samples</strong>) - select the checkbox above.</p> - <p>Please see the - <a href="#docs-file-phenotype-data" - title="Documentation of the phenotype data file format."> - "Phenotypes Data" documentation</a> section below for more information - on the expected format for the file provided here.</p>')}} - {{display_preview_table("tbl-preview-pheno-data", "phenotype data")}} - </div> - </fieldset> - - - {%if population.Family in families_with_se_and_n%} - <fieldset id="fldset-se-file"> - <div class="form-group"> - <div class="form-check"> - <input id="chk-phenotype-se-transposed" - name="phenotype-se-transposed" - type="checkbox" - class="form-check-input" - style="border: solid #8EABF0" /> - <label for="chk-phenotype-se-transposed" class="form-check-label"> - Standard-Errors file transposed?</label> - </div> - <div class="group non-resumable-elements"> - <label for="finput-phenotype-se" class="form-label">Phenotype: Standard Errors</label> - <input id="finput-phenotype-se" - name="phenotype-se" - class="form-control" - type="file" - data-preview-table="tbl-preview-pheno-se" - required="required" /> - <span class="form-text text-muted"> - Provide a file that contains only the standard errors for the phenotypes, - computed from the data above.</span> - </div> - - {{display_resumable_elements( - "resumable-phenotype-se", - "standard errors", - '<p>Drag and drop a CSV file that contains the phenotypes standard-errors - data here. You can click the "Browse" button (below and to the right) to - select the file from your computer.</p> - - <p>The CSV should be a matrix of <strong>samples × phenotypes</strong>, - i.e. The first column contains the samples identifiers while the first - row is the list of phenotypes identifiers occurring in the phenotypes - descriptions file.</p> - - <p>If the format is transposed (i.e <strong>phenotypes × samples</strong>) - select the checkbox above.</p> - - <p>Please see the - <a href="#docs-file-phenotype-se" - title="Documentation of the phenotype data file format."> - "Phenotypes Data" documentation</a> section below for more information - on the expected format of the file provided here.</p>')}} - - {{display_preview_table("tbl-preview-pheno-se", "standard errors")}} - </div> - </fieldset> - - - <fieldset id="fldset-n-file"> - <div class="form-group"> - <div class="form-check"> - <input id="chk-phenotype-n-transposed" - name="phenotype-n-transposed" - type="checkbox" - class="form-check-input" - style="border: solid #8EABF0" /> - <label for="chk-phenotype-n-transposed" class="form-check-label"> - Counts file transposed?</label> - </div> - <div class="non-resumable-elements"> - <label for="finput-phenotype-n" class="form-label">Phenotype: Number of Samples/Individuals</label> - <input id="finput-phenotype-n" - name="phenotype-n" - class="form-control" - type="file" - data-preview-table="tbl-preview-pheno-n" - required="required" /> - <span class="form-text text-muted"> - Provide a file that contains only the number of samples/individuals used in - the computation of the standard errors above.</span> - </div> - - {{display_resumable_elements( - "resumable-phenotype-n", - "number of samples/individuals", - '<p>Drag and drop a CSV file that contains the samples\' phenotypes counts - data here. You can click the "Browse" button (below and to the right) to - select the file from your computer.</p> - - <p>The CSV should be a matrix of <strong>samples × phenotypes</strong>, - i.e. The first column contains the samples identifiers while the first - row is the list of phenotypes identifiers occurring in the phenotypes - descriptions file.</p> - - <p>If the format is transposed (i.e <strong>phenotypes × samples</strong>) - select the checkbox above.</p> - - <p>Please see the - <a href="#docs-file-phenotype-se" - title="Documentation of the phenotype data file format."> - "Phenotypes Data" documentation</a> section below for more information - on the expected format of the file provided here.</p>')}} - - {{display_preview_table("tbl-preview-pheno-n", "number of samples/individuals")}} - </div> - </fieldset> -</fieldset> -{%endif%} -{%endblock%} - - -{%block page_documentation%} -<div class="row"> - <h2 class="heading" id="docs-help">Help</h2> - <h3 class="subheading">Common Features</h3> - <p>The following are the common expectations for <strong>ALL</strong> the - files provided in the form above: - <ul> - <li>The file <strong>MUST</strong> be character-separated values (CSV) - text file</li> - <li>The first row in the file <strong>MUST</strong> be a heading row, and - will be composed of the list identifiers for all of - samples/individuals/cases involved in your study.</li> - <li>The first column of data in the file <strong>MUST</strong> be the - identifiers for all of the phenotypes you wish to upload.</li> - </ul> - </p> - - <p>If you do not specify the separator character, then we will assume a - <strong>TAB</strong> character was used as your separator.</p> - - <p>We also assume you might include comments lines in your files. In that - case, if you do not specify what character denotes that a line in your files - is a comment line, we will assume the <strong>#</strong> character.<br /> - A comment <strong>MUST ALWAYS</strong> begin at the start of the line marked - with the comment character specified.</p> - - <h3 class="subheading" id="docs-file-metadata">File Metadata</h3> - <p>We request some details about your files to help us parse and process the - files correctly. The details we collect are:</p> - <dl> - <dt id="docs-file-separator">File separator</dt> - <dd>The files you provide should be character-separated value (CSV) files. - We need to know what character you used to separate the values in your - file. Some common ones are the Tab character, the comma, etc.<br /> - Providing that information makes it possible for the system to parse and - process your files correctly.<br> - <strong>NOTE:</strong> All the files you upload MUST use the same - separator.</dd> - - <dt id="docs-file-comment-character">Comment character</dt> - <dd>We support use of comment lines in your files. We only support one type - of comment style, the <em>line comment</em>.<br /> - This mean the comment begins at the start of the line, and the end of that - line indicates the end of that comment. If you have a really long comment, - then you need to break it across multiple lines, marking each line a - comment line.<br /> - The "comment character" is the character at the start of the line that - indicates that the line is a line comment.</dd> - - <dt id="docs-file-na">No-Value indicator(s)</dt> - <dd>Data in the real world is messy, and in some cases, entirely absent. You - need to indicate, in your files, that a particular field did not have a - value, and once you do that, you then need to let the system know how you - mark such fields. Common ways of indicating "empty values" are, leaving - the field blank, using a character such as '-', or using strings like - "NA", "N/A", "NULL", etc.<br /> - Providing this information will help with parsing and processing such - no-value fields the correct way.</dd> - </dl> - - <h3 class="subheading" id="docs-file-phenotype-description"> - file: Phenotypes Descriptions</h3> - <p>The data in this file is a matrix of <em>phenotypes × metadata-fields</em>. - Please note we use the term "metadata-fields" above loosely, due to lack of - a good word for this.</p> - <p>The file <strong>MUST</strong> have columns in this order: - <dl> - <dt>Phenotype Identifiers</dt> - <dd>These are the names/identifiers for your phenotypes. These - names/identifiers are the same ones you will have in all the other files you are - uploading.</dd> - - <dt>Descriptions</dt> - <dd>Each phenotype will need a description. Good description are necessary - to inform other people of what the data is about. Good description are - hard to construct, so we provide - <a href="https://info.genenetwork.org/faq.php#q-22" - title="How to write phenotype descriptions"> - advice on describing your phenotypes.</a></dd> - - <dt>Units</dt> - <dd>Each phenotype will need units for the measurements taken. If there are - none, then indicate the field is a no-value field.</dd> - </dl></p> - <p>You can add more columns after those three if you want to, but these 3 - <strong>MUST</strong> be present.</p> - <p>The file would, for example, look like the following:</p> - <code>id,description,units,…<br /> - pheno10001|Central nervous system, behavior, cognition; …|mg|…<br /> - pheno10002|Aging, metabolism, central nervous system: …|mg|…<br /> - ⋮<br /></code> - - <p><strong>Note 01</strong>: The first usable row is the heading row.</p> - <p><strong>Note 02: </strong>This example demonstrates a subtle issue that - could make your CSV file invalid — the choice of your field separator - character.<br > - In the example above, we use the pipe character (<code>|</code>) as our - field separator. This is because, if we follow the advice on how to write - good descriptions, then we cannot use the comma as our separator – if - we did, then our CSV file would be invalid because the system would have no - way to tell the difference between the comma as a field separator, and the - comma as a way to separate the "general category and ontology terms".</p> - - <h3 class="subheading">file: Phenotype Data, Standard Errors and/or Sample Counts</h3> - <span id="docs-file-phenotype-data"></span> - <span id="docs-file-phenotype-se"></span> - <span id="docs-file-phenotype-n"></span> - <p>The data is a matrix of <em>samples(or individuals) × phenotypes</em>, e.g.</p> - <code> - # num-cases: 2549 - # num-phenos: 13 - id,pheno10001,pheno10002,pheno10003,pheno10004,53.099998,…<br /> - IND001,61.400002,49,62.5,55.099998,…<br /> - IND002,54.099998,50.099998,53.299999,55.099998,…<br /> - IND003,483,403,501,403,…<br /> - IND004,49.799999,45.5,62.900002,NA,…<br /> - ⋮<br /></code> - - <p>where <code>IND001,IND002,IND003,IND004,…</code> are the - samples/individuals/cases in your study, and - <code>pheno10001,pheno10002,pheno10004,pheno10004,…</code> are the - identifiers for your phenotypes.</p> - <p>The lines beginning with the "<em>#</em>" symbol (i.e. - <code># num-cases: 2549</code> and <code># num-phenos: 13</code> are comment - lines and will be ignored</p> - <p>In this example, the comma (,) is used as the file separator.</p> -</div> - -{%endblock%} - - -{%block more_javascript%} -<script src="{{url_for('base.node_modules', - filename='resumablejs/resumable.js')}}"></script> -<script type="text/javascript" src="/static/js/files.js"></script> - -<script type="text/javascript"> - $("#btn-reset-file-separator").on("click", (event) => { - event.preventDefault(); - $("#txt-file-separator").val("\t"); - $("#txt-file-separator").trigger("change"); - }); - $("#btn-reset-file-comment-character").on("click", (event) => { - event.preventDefault(); - $("#txt-file-comment-character").val("#"); - $("#txt-file-comment-character").trigger("change"); - }); - $("#btn-reset-file-na").on("click", (event) => { - event.preventDefault(); - $("#txt-file-na").val("- NA N/A"); - $("#txt-file-na").trigger("change"); - }); - - var update_preview = (table, filedata, formdata, numrows) => { - table.find("thead tr").remove() - table.find(".data-row").remove(); - var linenum = 0; - var tableheader = table.find("thead"); - var tablebody = table.find("tbody"); - var numheadings = 0; - var navalues = formdata - .na_strings - .split(" ") - .map((v) => {return v.trim();}) - .filter((v) => {return Boolean(v);}); - filedata.forEach((line) => { - if(line.startsWith(formdata.comment_char) || linenum >= numrows) { - return false; - } - var row = $("<tr></tr>"); - line.split(formdata.separator) - .map((field) => { - var value = field.trim(); - if(navalues.includes(value)) { - return "⋘NUL⋙"; - } - return value; - }) - .filter((field) => { - return (field !== "" && field != undefined && field != null); - }) - .forEach((field) => { - if(linenum == 0) { - numheadings += 1; - var tablefield = $("<th></th>"); - tablefield.text(field); - row.append(tablefield); - } else { - add_class(row, "data-row"); - var tablefield = $("<td></td>"); - tablefield.text(field); - row.append(tablefield); - } - }); - - if(linenum == 0) { - tableheader.append(row); - } else { - tablebody.append(row); - } - linenum += 1; - }); - - if(table.find("tbody tr.data-row").length > 0) { - add_class(table.find(".data-row-template"), "visually-hidden"); - } else { - remove_class(table.find(".data-row-template"), "visually-hidden"); - } - }; - - var makePreviewUpdater = (preview_table) => { - return (data) => { - update_preview( - preview_table, - data, - filesMetadata(), - PREVIEW_ROWS); - }; - }; - - var preview_tables_to_elements_map = { - "#tbl-preview-pheno-desc": "#finput-phenotype-descriptions", - "#tbl-preview-pheno-data": "#finput-phenotype-data", - "#tbl-preview-pheno-se": "#finput-phenotype-se", - "#tbl-preview-pheno-n": "#finput-phenotype-n" - }; - - var filesMetadata = () => { - return { - "separator": $("#txt-file-separator").val(), - "comment_char": $( - "#txt-file-comment-character").val(), - "na_strings": $("#txt-file-na").val() - } - }; - - var PREVIEW_ROWS = 5; - - var handler_update_previews = (event) => { - Object.entries(preview_tables_to_elements_map).forEach((mapentry) => { - var preview_table = $(mapentry[0]); - var file_input = $(mapentry[1]); - if(file_input[0].files.length > 0) { - readFirstNLines( - file_input[0].files[0], - 10, - [makePreviewUpdater(preview_table)]); - } - }); - - if(typeof(resumables) !== "undefined") { - resumables.forEach((resumable) => { - if(resumable.files.length > 0) { - readFirstNLines( - resumable.files[0].file, - 10, - [makePreviewUpdater(resumable.preview_table)]); - } - }); - } - }; - - [ - "#txt-file-separator", - "#txt-file-comment-character", - "#txt-file-na" - ].forEach((elementid) => { - $(elementid).on("change", handler_update_previews); - }); - - [ - "#finput-phenotype-descriptions", - "#finput-phenotype-data", - "#finput-phenotype-se", - "#finput-phenotype-n" - ].forEach((elementid) => { - $(elementid).on("change", (event) => { - readFirstNLines( - event.target.files[0], - 10, - [makePreviewUpdater( - $("#" + event.target.getAttribute("data-preview-table")))]); - }); - }); - - - var resumableDisplayFiles = (display_area, files) => { - files.forEach((file) => { - display_area.find(".file-display").remove(); - var display_element = display_area - .find(".file-display-template") - .clone(); - remove_class(display_element, "visually-hidden"); - remove_class(display_element, "file-display-template"); - add_class(display_element, "file-display"); - display_element.find(".filename").text(file.name - || file.fileName - || file.relativePath - || file.webkitRelativePath); - display_element.find(".filesize").text( - (file.size / (1024*1024)).toFixed(2) + "MB"); - display_element.find(".fileuniqueid").text(file.uniqueIdentifier); - display_element.find(".filemimetype").text(file.file.type); - display_area.append(display_element); - }); - }; - - - var indicateProgress = (resumable, progress_bar) => { - return () => {/*Has no event!*/ - var progress = (resumable.progress() * 100).toFixed(2); - var pbar = progress_bar.find(".progress-bar"); - remove_class(progress_bar, "visually-hidden"); - pbar.css("width", progress+"%"); - pbar.attr("aria-valuenow", progress); - pbar.text("Uploading: " + progress + "%"); - }; - }; - - var retryUpload = (retry_button, cancel_button) => { - retry_button.on("click", (event) => { - resumable.files.forEach((file) => {file.retry();}); - add_class(retry_button, "visually-hidden"); - remove_class(cancel_button, "visually-hidden"); - add_class(browse_button, "visually-hidden"); - }); - }; - - var cancelUpload = (cancel_button, retry_button) => { - cancel_button.on("click", (event) => { - resumable.files.forEach((file) => { - if(file.isUploading()) { - file.abort(); - } - }); - add_class(cancel_button, "visually-hidden"); - remove_class(retry_button, "visually-hidden"); - remove_class(browse_button, "visually-hidden"); - }); - }; - - - var startUpload = (browse_button, retry_button, cancel_button) => { - return (event) => { - remove_class(cancel_button, "visually-hidden"); - add_class(retry_button, "visually-hidden"); - add_class(browse_button, "visually-hidden"); - }; - }; - - var processForm = (form) => { - var formdata = new FormData(form); - uploaded_files.forEach((msg) => { - formdata.delete(msg["file-input-name"]); - formdata.append(msg["file-input-name"], JSON.stringify({ - "uploaded-file": msg["uploaded-file"], - "original-name": msg["original-name"] - })); - }); - formdata.append("resumable-upload", "true"); - formdata.append("publication-id", $("#txt-publication-id").val()); - return formdata; - } - - var uploaded_files = new Set(); - var submitForm = (new_file) => { - uploaded_files.add(new_file); - if(uploaded_files.size === resumables.length) { - var form = $("#frm-add-phenotypes"); - if(form.length !== 1) { - // TODO: Handle error somehow? - alert("Could not find form!!!"); - return false; - } - - $.ajax({ - "url": form.attr("action"), - "type": "POST", - "data": processForm(form[0]), - "processData": false, - "contentType": false, - "success": (data, textstatus, jqxhr) => { - // TODO: Redirect to endpoint that should come as part of the - // success/error message. - console.log("SUCCESS DATA: ", data); - console.log("SUCCESS STATUS: ", textstatus); - console.log("SUCCESS jqXHR: ", jqxhr); - window.location.assign(window.location.origin + data["redirect-to"]); - }, - }); - return false; - } - return false; - }; - - var uploadSuccess = (file_input_name) => { - return (file, message) => { - submitForm({...JSON.parse(message), "file-input-name": file_input_name}); - }; - }; - - - var uploadError = () => { - return (message, file) => { - $("#frm-add-phenotypes input[type=submit]").removeAttr("disabled"); - console.log("THE FILE:", file); - console.log("THE ERROR MESSAGE:", message); - }; - }; - - - - var makeResumableObject = (form_id, file_input_id, resumable_element_id, preview_table_id) => { - var the_form = $("#" + form_id); - var file_input = $("#" + file_input_id); - var submit_button = the_form.find("input[type=submit]"); - if(file_input.length != 1) { - return false; - } - var r = errorHandler( - fileSuccessHandler( - uploadStartHandler( - filesAddedHandler( - markResumableDragAndDropElement( - makeResumableElement( - the_form.attr("data-resumable-target"), - file_input.parent(), - $("#" + resumable_element_id), - submit_button, - ["csv", "tsv", "txt"]), - file_input.parent(), - $("#" + resumable_element_id), - $("#" + resumable_element_id + "-browse-button")), - (files) => { - // TODO: Also trigger preview! - resumableDisplayFiles( - $("#" + resumable_element_id + "-selected-files"), files); - files.forEach((file) => { - readFirstNLines( - file.file, - 10, - [makePreviewUpdater( - $("#" + preview_table_id))]) - }); - }), - startUpload($("#" + resumable_element_id + "-browse-button"), - $("#" + resumable_element_id + "-retry-button"), - $("#" + resumable_element_id + "-cancel-button"))), - uploadSuccess(file_input.attr("name"))), - uploadError()); - - /** Setup progress indicator **/ - progressHandler( - r, - indicateProgress(r, $("#" + resumable_element_id + "-progress-bar"))); - - return r; - }; - - var resumables = [ - ["frm-add-phenotypes", "finput-phenotype-descriptions", "resumable-phenotype-descriptions", "tbl-preview-pheno-desc"], - ["frm-add-phenotypes", "finput-phenotype-data", "resumable-phenotype-data", "tbl-preview-pheno-data"], - ["frm-add-phenotypes", "finput-phenotype-se", "resumable-phenotype-se", "tbl-preview-pheno-se"], - ["frm-add-phenotypes", "finput-phenotype-n", "resumable-phenotype-n", "tbl-preview-pheno-n"], - ].map((row) => { - r = makeResumableObject(row[0], row[1], row[2], row[3]); - r.preview_table = $("#" + row[3]); - return r; - }).filter((val) => { - return Boolean(val); - }); - - $("#frm-add-phenotypes input[type=submit]").on("click", (event) => { - event.preventDefault(); - console.debug(); - if ($("#txt-publication-id").val() == "") { - alert("You MUST provide a publication for the phenotypes."); - return false; - } - // TODO: Check all the relevant files exist - // TODO: Verify that files are not duplicated - var filenames = []; - var nondupfiles = []; - resumables.forEach((r) => { - var fname = r.files[0].file.name; - filenames.push(fname); - if(!nondupfiles.includes(fname)) { - nondupfiles.push(fname); - } - }); - - // Check that all files were provided - if(resumables.length !== filenames.length) { - window.alert("You MUST provide all the files requested."); - event.target.removeAttribute("disabled"); - return false; - } - - // Check that there are no duplicate files - var duplicates = Object.entries(filenames.reduce( - (acc, curr, idx, arr) => { - acc[curr] = (acc[curr] || 0) + 1; - return acc; - }, - {})).filter((entry) => {return entry[1] !== 1;}); - if(duplicates.length > 0) { - var msg = "The file(s):\r\n"; - msg = msg + duplicates.reduce( - (msgstr, afile) => { - return msgstr + " • " + afile[0] + "\r\n"; - }, - ""); - msg = msg + "is(are) duplicated. Please fix and try again."; - window.alert(msg); - event.target.removeAttribute("disabled"); - return false; - } - // TODO: Check all fields - // Start the uploads. - event.target.setAttribute("disabled", "disabled"); - resumables.forEach((r) => {r.upload();}); - }); -</script> -{%endblock%} diff --git a/uploader/templates/phenotypes/sui-add-phenotypes-with-rqtl2-bundle.html b/uploader/templates/phenotypes/sui-add-phenotypes-with-rqtl2-bundle.html deleted file mode 100644 index 29a8dea..0000000 --- a/uploader/templates/phenotypes/sui-add-phenotypes-with-rqtl2-bundle.html +++ /dev/null @@ -1,189 +0,0 @@ -{%extends "phenotypes/sui-add-phenotypes-base.html"%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block frm_add_phenotypes_documentation%} -<p>Select the zip file bundle containing information on the phenotypes you - wish to upload, then click the "Upload Phenotypes" button below to - upload the data.</p> -<p>If you wish to upload the files individually instead, - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}" - title="">click here</a>.</p> -<p>See the <a href="#section-file-formats">File Formats</a> section below - to get an understanding of what is expected of the bundle files you - upload.</p> -{%endblock%} - -{%block frm_add_phenotypes_elements%} -<div class="form-group"> - <label for="finput-phenotypes-bundle" class="form-label"> - Phenotypes Bundle</label> - <input type="file" - id="finput-phenotypes-bundle" - name="phenotypes-bundle" - accept="application/zip, .zip" - required="required" - class="form-control" /> -</div> -{%endblock%} - -{%block page_documentation%} -<div class="row"> - <h2 class="heading" id="section-file-formats">File Formats</h2> - <p>We accept an extended form of the - <a href="https://kbroman.org/qtl2/assets/vignettes/input_files.html#format-of-the-data-files" - title="R/qtl2 software input file format documentation"> - input files' format used with the R/qtl2 software</a> as a single ZIP - file</p> - <p>The files that are used for this feature are: - <ul> - <li>the <em>control</em> file</li> - <li><em>pheno</em> file(s)</li> - <li><em>phenocovar</em> file(s)</li> - <li><em>phenose</em> files(s)</li> - </ul> - </p> - <p>Other files within the bundle will be ignored, for this feature.</p> - <p>The following section will detail the expectations for each of the - different file types within the uploaded ZIP file bundle for phenotypes:</p> - - <h3 class="subheading">Control File</h3> - <p>There <strong>MUST be <em>one, and only one</em></strong> file that acts - as the control file. This file can be: - <ul> - <li>a <em>JSON</em> file, or</li> - <li>a <em>YAML</em> file.</li> - </ul> - </p> - - <p>The control file is useful for defining things about the bundle such as:</p> - <ul> - <li>The field separator value (default: <code>sep: ','</code>). There can - only ever be one field separator and it <strong>MUST</strong> be the same - one for <strong>ALL</strong> files in the bundle.</li> - <li>The comment character (default: <code>comment.char: '#'</code>). Any - line that starts with this character will be considered a comment line and - be ignored in its entirety.</li> - <li>Code for missing values (default: <code>na.strings: 'NA'</code>). You - can specify more than one code to indicate missing values, e.g. - <code>{…, "na.strings": ["NA", "N/A", "-"], …}</code></li> - </ul> - - <h3 class="subheading"><em>pheno</em> File(s)</h3> - <p>These files are the main data files. You must have at least one of these - files in your bundle for it to be valid for this step.</p> - <p>The data is a matrix of <em>individuals × phenotypes</em> by default, as - below:<br /> - <code> - id,10001,10002,10003,10004,…<br /> - BXD1,61.400002,54.099998,483,49.799999,…<br /> - BXD2,49,50.099998,403,45.5,…<br /> - BXD5,62.5,53.299999,501,62.900002,…<br /> - BXD6,53.099998,55.099998,403,NA,…<br /> - ⋮<br /></code> - </p> - <p>If the <code>pheno_transposed</code> value is set to <code>True</code>, - then the data will be a <em>phenotypes × individuals</em> matrix as in the - example below:<br /> - <code> - id,BXD1,BXD2,BXD5,BXD6,…<br /> - 10001,61.400002,49,62.5,53.099998,…<br /> - 10002,54.099998,50.099998,53.299999,55.099998,…<br /> - 10003,483,403,501,403,…<br /> - 10004,49.799999,45.5,62.900002,NA,…<br /> - ⋮ - </code> - </p> - - - <h3 class="subheading"><em>phenocovar</em> File(s)</h3> - <p>At least one phenotypes metadata file with the metadata values such as - descriptions, PubMed Identifier, publication titles (if present), etc.</p> - <p>The data in this/these file(s) is a matrix of - <em>phenotypes × phenotypes-covariates</em>. The first column is always the - phenotype names/identifiers — same as in the R/qtl2 format.</p> - <p><em>phenocovar</em> files <strong>should never be transposed</strong>!</p> - <p>This file <strong>MUST</strong> be present in the bundle, and have data for - the bundle to be considered valid by our system for this step.<br /> - In addition to that, the following are the fields that <strong>must be - present</strong>, and - have values, in the file before the file is considered valid: - <ul> - <li><em>description</em>: A description for each phenotype. Useful - for users to know what the phenotype is about.</li> - <li><em>units</em>: The units of measurement for the phenotype, - e.g. milligrams for brain weight, centimetres/millimetres for - tail-length, etc.</li> - </ul></p> - - <p>The following <em>optional</em> fields can also be provided: - <ul> - <li><em>pubmedid</em>: A PubMed Identifier for the publication where - the phenotype is published. If this field is not provided, the system will - assume your phenotype is not published.</li> - </ul> - </p> - <p>These files will be marked up in the control file with the - <code>phenocovar</code> key, as in the examples below: - <ol> - <li>JSON: single file<br /> - <code>{<br /> - ⋮,<br /> - "phenocovar": "your_covariates_file.csv",<br /> - ⋮<br /> - } - </code> - </li> - <li>JSON: multiple files<br /> - <code>{<br /> - ⋮,<br /> - "phenocovar": [<br /> - "covariates_file_01.csv",<br /> - "covariates_file_01.csv",<br /> - ⋮<br /> - ],<br /> - ⋮<br /> - } - </code> - </li> - <li>YAML: single file or<br /> - <code> - ⋮<br /> - phenocovar: your_covariates_file.csv<br /> - ⋮ - </code> - </li> - <li>YAML: multiple files<br /> - <code> - ⋮<br /> - phenocovar:<br /> - - covariates_file_01.csv<br /> - - covariates_file_02.csv<br /> - - covariates_file_03.csv<br /> - …<br /> - ⋮ - </code> - </li> - </ol> - </p> - - <h3 class="subheading"><em>phenose</em> and <em>phenonum</em> File(s)</h3> - <p>These are extensions to the R/qtl2 standard, i.e. these types ofs file are - not supported by the original R/qtl2 file format</p> - <p>We use these files to upload the standard errors (<em>phenose</em>) when - the data file (<em>pheno</em>) is average data. In that case, the - <em>phenonum</em> file(s) contains the number of individuals that were - involved when computing the averages.</p> - <p>Both types of files are matrices of <em>individuals × phenotypes</em> by - default. Like the related <em>pheno</em> files, if - <code>pheno_transposed: True</code>, then the file will be a matrix of - <em>phenotypes × individuals</em>.</p> -</div> -{%endblock%} diff --git a/uploader/templates/phenotypes/sui-base.html b/uploader/templates/phenotypes/sui-base.html deleted file mode 100644 index d7d980f..0000000 --- a/uploader/templates/phenotypes/sui-base.html +++ /dev/null @@ -1,25 +0,0 @@ -{%extends "populations/sui-base.html"%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_sui_pheno_dataset_card%} - -{%block breadcrumbs%} -{{super()}} -<li class="breadcrumb-item"> - <a href="{{url_for('species.populations.phenotypes.view_dataset', - species_id=species['SpeciesId'], - population_id=population['Id'], - dataset_id=dataset['Id'])}}"> - {{dataset["Name"]}} - </a> -</li> -{%endblock%} - -{%block contents%} -<div class="row"> - <h2 class="heading">{{dataset.FullName}} ({{dataset.Name}})</h2> -</div> -{%endblock%} - - -{%block sidebarcontents%} -{{display_sui_pheno_dataset_card(species, population, dataset)}} -{%endblock%} diff --git a/uploader/templates/phenotypes/sui-job-status.html b/uploader/templates/phenotypes/sui-job-status.html deleted file mode 100644 index bca87d5..0000000 --- a/uploader/templates/phenotypes/sui-job-status.html +++ /dev/null @@ -1,140 +0,0 @@ -{%extends "phenotypes/sui-base.html"%} -{%from "cli-output.html" import cli_output%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} - -{%block extrameta%} -{%if job and job.status not in ("success", "completed:success", "error", "completed:error")%} -<meta http-equiv="refresh" content="5" /> -{%endif%} -{%endblock%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block contents%} - -{%if job%} -<div class="row"> - <h2 class="heading">{{dataset.FullName}} ({{dataset.Name}})</h2> - <h3 class="subheading">upload progress</h3> -</div> -<div class="row" style="overflow:scroll;"> - <p><strong>Process Status:</strong> {{job.status}}</p> - {%if metadata%} - <table class="table table-responsive"> - <thead> - <tr> - <th>File</th> - <th>Status</th> - <th>Lines Processed</th> - <th>Total Errors</th> - </tr> - </thead> - - <tbody> - {%for file,meta in metadata.items()%} - <tr> - <td>{{file}}</td> - <td>{{meta.status}}</td> - <td>{{meta.linecount}}</td> - <td>{{meta["total-errors"]}}</td> - </tr> - {%endfor%} - </tbody> - </table> - {%endif%} -</div> - -<div class="row"> - {%if job.status in ("completed:success", "success")%} - <p> - {%if errors | length == 0%} - <a href="{{url_for('species.populations.phenotypes.review_job_data', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id, - job_id=job_id)}}" - class="btn btn-primary" - title="Continue to process data">Continue</a> - {%else%} - <span class="text-muted" - disabled="disabled" - style="border: solid 2px;border-radius: 5px;padding: 0.3em;"> - Cannot continue due to errors. Please fix the errors first. - </span> - {%endif%} - </p> - {%endif%} -</div> - -<h3 class="subheading">upload errors</h3> -<div class="row" style="max-height: 20em; overflow: scroll;"> - {%if errors | length == 0 %} - <p class="text-info"> - <span class="glyphicon glyphicon-info-sign"></span> - No errors found so far - </p> - {%else%} - <table class="table table-responsive"> - <thead style="position: sticky; top: 0; background: white;"> - <tr> - <th>File</th> - <th>Row</th> - <th>Column</th> - <th>Value</th> - <th>Message</th> - </tr> - </thead> - - <tbody style="font-size: 0.9em;"> - {%for error in errors%} - <tr> - <td>{{error.filename}}</td> - <td>{{error.rowtitle}}</td> - <td>{{error.coltitle}}</td> - <td>{%if error.cellvalue is not none and error.cellvalue | length > 25%} - {{error.cellvalue[0:24]}}… - {%else%} - {{error.cellvalue}} - {%endif%} - </td> - <td> - {%if error.message | length > 250 %} - {{error.message[0:249]}}… - {%else%} - {{error.message}} - {%endif%} - </td> - </tr> - {%endfor%} - </tbody> - </table> - {%endif%} -</div> - -<div class="row"> - {{cli_output(job, "stdout")}} -</div> - -<div class="row"> - {{cli_output(job, "stderr")}} -</div> - -{%else%} -<div class="row"> - <h3 class="text-danger">No Such Job</h3> - <p>Could not find a job with the ID: {{job_id}}</p> - <p> - Please go back to - <a href="{{url_for('species.populations.phenotypes.view_dataset', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}" - title="'{{dataset.Name}}' dataset page"> - the '{{dataset.Name}}' dataset page</a> - to upload new phenotypes or edit existing ones.</p> -</div> -{%endif%} -{%endblock%} diff --git a/uploader/templates/phenotypes/sui-load-phenotypes-success.html b/uploader/templates/phenotypes/sui-load-phenotypes-success.html deleted file mode 100644 index dff0682..0000000 --- a/uploader/templates/phenotypes/sui-load-phenotypes-success.html +++ /dev/null @@ -1,26 +0,0 @@ -{%extends "phenotypes/sui-base.html"%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block contents%} -{{super()}} - -<div class="row"> - <p>You have successfully loaded - <!-- maybe indicate the number of phenotypes here? -->your - new phenotypes into the database.</p> - <!-- TODO: Maybe notify user that they have sole access. --> - <!-- TODO: Maybe provide a link to go to GeneNetwork to view the data. --> - <p>View your data - <a href="{{search_page_uri}}" - target="_blank">on GeneNetwork2</a>. - You might need to login to GeneNetwork2 to view specific traits.</p> -</div> -{%endblock%} - - -{%block more_javascript%}{%endblock%} diff --git a/uploader/templates/phenotypes/sui-review-job-data.html b/uploader/templates/phenotypes/sui-review-job-data.html deleted file mode 100644 index ea4183d..0000000 --- a/uploader/templates/phenotypes/sui-review-job-data.html +++ /dev/null @@ -1,121 +0,0 @@ -{%extends "phenotypes/sui-base.html"%} -{%from "cli-output.html" import cli_output%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} -{%from "phenotypes/macro-display-pheno-dataset-card.html" import display_pheno_dataset_card%} - -{%block extrameta%} -{%if not job%} -<meta http-equiv="refresh" - content="20; url={{url_for('species.populations.phenotypes.view_dataset', species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}" /> -{%endif%} -{%endblock%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block lvl4_breadcrumbs%} -<li {%if activelink=="add-phenotypes"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">View Datasets</a> -</li> -{%endblock%} - -{%block contents%} - -{%if job%} -<div class="row"> - <h3 class="heading">Data Review</h3> - <p class="text-info"><strong> - The data has <em>NOT</em> been added/saved yet. Review the details below - and click "Continue" to save the data.</strong></p> - <p>The “<strong>{{dataset.FullName}}</strong>” dataset from the - “<strong>{{population.FullName}}</strong>” population of the - species “<strong>{{species.SpeciesName}} ({{species.FullName}})</strong>” - will be updated as follows:</p> - - <ul> - {%if publication%} - <li>All {{summary.get("pheno", {}).get("total-data-rows", "0")}} phenotypes - are linked to the following publication: - <ul> - <li><strong>Publication Title:</strong> - {{publication.Title or "—"}}</li> - <li><strong>Author(s):</strong> - {{publication.Authors or "—"}}</li> - </ul> - </li> - {%endif%} - {%for ftype in ("phenocovar", "pheno", "phenose", "phenonum")%} - {%if summary.get(ftype, False)%} - <li>A total of {{summary[ftype]["number-of-files"]}} files will be processed - adding {%if ftype == "phenocovar"%}(possibly){%endif%} - {{summary[ftype]["total-data-rows"]}} new - {%if ftype == "phenocovar"%} - phenotypes - {%else%} - {{summary[ftype]["description"]}} rows - {%endif%} - to the database. - </li> - {%endif%} - {%endfor%} - </ul> - - <form id="frm-review-phenotype-data" - method="POST" - action="{{url_for('species.populations.phenotypes.load_data_to_database', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}"> - <input type="hidden" name="data-qc-job-id" value="{{job.jobid}}" /> - <input type="submit" - value="continue" - class="btn btn-primary" /> - </form> -</div> -{%else%} -<div class="row"> - <h4 class="subheading">Invalid Job</h3> - <p class="text-danger"> - Could not find a job with the ID: <strong>{{job_id}}.</p> - <p>You will be redirected in - <span id="countdown-element" class="text-info">20</span> second(s)</p> - <p class="text-muted"> - <small> - If you are not redirected, please - <a href="{{url_for( - 'species.populations.phenotypes.view_dataset', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">click here</a> to continue - </small> - </p> -</div> -{%endif%} -{%endblock%} - - -{%block javascript%} -<script type="text/javascript"> - $(document).ready(function() { - var countdown = 20; - var countdown_element = $("#countdown-element"); - if(countdown_element.length === 1) { - intv = window.setInterval(function() { - countdown = countdown - 1; - countdown_element.html(countdown); - }, 1000); - } - }); -</script> -{%endblock%} diff --git a/uploader/templates/phenotypes/sui-view-dataset.html b/uploader/templates/phenotypes/sui-view-dataset.html deleted file mode 100644 index f858c4e..0000000 --- a/uploader/templates/phenotypes/sui-view-dataset.html +++ /dev/null @@ -1,207 +0,0 @@ -{%extends "phenotypes/sui-base.html"%} -{%from "flash_messages.html" import flash_all_messages%} -{%from "macro-table-pagination.html" import table_pagination%} - -{%block title%}Phenotypes{%endblock%} - -{%block pagetitle%}Phenotypes{%endblock%} - -{%block lvl4_breadcrumbs%} -<li {%if activelink=="view-dataset"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.view_dataset', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}">View</a> -</li> -{%endblock%} - -{%block contents%} -{{flash_all_messages()}} - -<div class="row"> - <p>The basic dataset details are:</p> - - <table class="table"> - <thead> - <tr> - <th>Name</th> - <th>Full Name</th> - <th>Short Name</th> - </tr> - </thead> - - <tbody> - <tr> - <td>{{dataset.Name}}</td> - <td>{{dataset.FullName}}</td> - <td>{{dataset.ShortName}}</td> - </tr> - </tbody> - </table> -</div> - -<div class="row"> - <div class="col"> - <a href="{{url_for('species.populations.phenotypes.add_phenotypes', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id)}}" - title="Add a bunch of phenotypes" - class="btn btn-primary">Add phenotypes</a> - </div> - - <div class="col"> - <form id="frm-recompute-phenotype-means" - method="POST" - action="{{url_for( - 'species.populations.phenotypes.recompute_means', - species_id=species['SpeciesId'], - population_id=population['Id'], - dataset_id=dataset['Id'])}}" - class="d-flex flex-row align-items-center flex-wrap" - style="display: inline;"> - <input type="submit" - title="Compute/Recompute the means for all phenotypes." - class="btn btn-info" - value="(rec/c)ompute means" - id="submit-frm-recompute-phenotype-means" /> - </form> - </div> - - <div class="col"> - <form id="frm-run-qtlreaper" - method="POST" - action="{{url_for( - 'species.populations.phenotypes.rerun_qtlreaper', - species_id=species['SpeciesId'], - population_id=population['Id'], - dataset_id=dataset['Id'])}}" - class="d-flex flex-row align-items-center flex-wrap" - style="display: inline;"> - <input type="submit" - title="Run/Rerun QTLReaper." - class="btn btn-info" - value="(re)run QTLReaper" - id="submit-frm-rerun-qtlreaper" /> - </form> - </div> -</div> - -<div class="row"> - <h2>Phenotype Data</h2> - - <p>Click on any of the phenotypes in the table below to view and edit that - phenotype's data.</p> - <p>Use the search to filter through all the phenotypes and find specific - phenotypes of interest.</p> -</div> - - -<div class="row"> - - <table id="tbl-phenotypes-list" class="table compact stripe cell-border"> - <thead> - <tr> - <th></th> - <th>Index</th> - <th>Record</th> - <th>Description</th> - </tr> - </thead> - - <tbody></tbody> - </table> -</div> -{%endblock%} - - -{%block javascript%} -<script type="text/javascript" src="/static/js/urls.js"></script> - -<script type="text/javascript"> - $(function() { - var species_id = {{species.SpeciesId}}; - var population_id = {{population.Id}}; - var dataset_id = {{dataset.Id}}; - var dataset_name = "{{dataset.Name}}"; - var data = {{phenotypes | tojson}}; - - var dtPhenotypesList = buildDataTable( - "#tbl-phenotypes-list", - data, - [ - { - data: function(pheno) { - return `<input type="checkbox" name="selected-phenotypes" ` - + `id="chk-selected-phenotypes-${pheno.InbredSetCode}_${pheno.xref_id}" ` - + `value="${pheno.InbredSetCode}_${pheno.xref_id}" ` - + `class="chk-row-select" />` - } - }, - {data: "sequence_number"}, - { - data: function(pheno, type, set, meta) { - var spcs_id = {{species.SpeciesId}}; - var pop_id = {{population.Id}}; - var dtst_id = {{dataset.Id}}; - var url = buildURLFromCurrentURL( - (`/species/${spcs_id}` + - `/populations/${pop_id}` + - `/phenotypes/datasets/${dtst_id}` + - `/phenotype/${pheno.xref_id}`)); - return `<a href="${url.toString()}" target="_blank">` + - `${pheno.InbredSetCode}_${pheno.xref_id}` + - `</a>`; - } - }, - { - data: function(pheno) { - return (pheno.Post_publication_description || - pheno.Original_description || - pheno.Pre_publication_description); - } - } - ], - { - select: "multi+shift", - layout: { - top1Start: { - pageLength: { - text: "Show _MENU_ of _TOTAL_" - } - }, - topStart: "info", - top1End: null - }, - rowId: function(pheno) { - return `${pheno.InbredSetCode}_${pheno.xref_id}`; - } - }); - - - $("#submit-frm-rerun-qtlreaper").on( - "click", - function(event) { - // (Re)run the QTLReaper script for selected phenotypes. - event.preventDefault(); - var form = $("#frm-run-qtlreaper"); - form.find(".dynamically-added-element").remove(); - dtPhenotypesList.rows({selected: true}).nodes().each((node, index) => { - _cloned = $(node).find(".chk-row-select").clone(); - _cloned.removeAttr("id"); - _cloned.removeAttr("class"); - _cloned.attr("style", "display: none;"); - _cloned.attr("data-type", "dynamically-added-element"); - _cloned.attr("class", "dynamically-added-element checkbox"); - _cloned.prop("checked", true); - form.append(_cloned); - }); - form.submit(); - }); - }); -</script> -{%endblock%} diff --git a/uploader/templates/phenotypes/view-dataset.html b/uploader/templates/phenotypes/view-dataset.html index c634a48..1fd15b2 100644 --- a/uploader/templates/phenotypes/view-dataset.html +++ b/uploader/templates/phenotypes/view-dataset.html @@ -1,7 +1,6 @@ {%extends "phenotypes/base.html"%} {%from "flash_messages.html" import flash_all_messages%} {%from "macro-table-pagination.html" import table_pagination%} -{%from "populations/macro-display-population-card.html" import display_population_card%} {%block title%}Phenotypes{%endblock%} @@ -119,12 +118,10 @@ </div> {%endblock%} -{%block sidebarcontents%} -{{display_population_card(species, population)}} -{%endblock%} - {%block javascript%} +<script type="text/javascript" src="/static/js/urls.js"></script> + <script type="text/javascript"> $(function() { var species_id = {{species.SpeciesId}}; @@ -151,11 +148,12 @@ var spcs_id = {{species.SpeciesId}}; var pop_id = {{population.Id}}; var dtst_id = {{dataset.Id}}; - return `<a href="/species/${spcs_id}` + + var url = buildURLFromCurrentURL( + (`/species/${spcs_id}` + `/populations/${pop_id}` + `/phenotypes/datasets/${dtst_id}` + - `/phenotype/${pheno.xref_id}` + - `" target="_blank">` + + `/phenotype/${pheno.xref_id}`)); + return `<a href="${url.toString()}" target="_blank">` + `${pheno.InbredSetCode}_${pheno.xref_id}` + `</a>`; } diff --git a/uploader/templates/phenotypes/view-phenotype.html b/uploader/templates/phenotypes/view-phenotype.html index 75e3c1e..a69b024 100644 --- a/uploader/templates/phenotypes/view-phenotype.html +++ b/uploader/templates/phenotypes/view-phenotype.html @@ -1,25 +1,10 @@ {%extends "phenotypes/base.html"%} {%from "flash_messages.html" import flash_all_messages%} -{%from "populations/macro-display-population-card.html" import display_population_card%} {%block title%}Phenotypes{%endblock%} {%block pagetitle%}Phenotypes{%endblock%} -{%block lvl4_breadcrumbs%} -<li {%if activelink=="view-phenotype"%} - class="breadcrumb-item active" - {%else%} - class="breadcrumb-item" - {%endif%}> - <a href="{{url_for('species.populations.phenotypes.view_phenotype', - species_id=species.SpeciesId, - population_id=population.Id, - dataset_id=dataset.Id, - xref_id=xref_id)}}">View Phenotype</a> -</li> -{%endblock%} - {%block contents%} {{flash_all_messages()}} @@ -153,7 +138,3 @@ or "group:resource:delete-resource" in privileges%} </div> {%endblock%} - -{%block sidebarcontents%} -{{display_population_card(species, population)}} -{%endblock%} |
