From 99c8e2243b7c37f2284189984e37a26742a21b3b Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Fri, 6 May 2022 10:59:05 -0600 Subject: [PATCH 01/33] Adding files --- CRISPRessoReport.py | 636 +++++++++++++++++++++++ templates/CRISPResso_justcup.png | Bin 0 -> 42782 bytes templates/favicon.ico | Bin 0 -> 1150 bytes templates/layout.html | 104 ++++ templates/multiReport.html | 285 +++++++++++ templates/report.html | 854 +++++++++++++++++++++++++++++++ 6 files changed, 1879 insertions(+) create mode 100644 CRISPRessoReport.py create mode 100644 templates/CRISPResso_justcup.png create mode 100644 templates/favicon.ico create mode 100644 templates/layout.html create mode 100644 templates/multiReport.html create mode 100644 templates/report.html diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py new file mode 100644 index 00000000..a49f2584 --- /dev/null +++ b/CRISPRessoReport.py @@ -0,0 +1,636 @@ +''' +CRISPResso2 - Kendell Clement and Luca Pinello 2018 +Software pipeline for the analysis of genome editing outcomes from deep sequencing data +(c) 2020 The General Hospital Corporation. All Rights Reserved. +''' + +import os +from jinja2 import Environment, FileSystemLoader +from CRISPResso2 import CRISPRessoShared + + +def make_report_from_folder(crispresso_report_file, crispresso_folder, _ROOT): + """ + Makes an html report for a crispresso run + + Parameters: + crispresso_report_file (string): name of the html file to create + crispresso_folder (string): path to the crispresso output + _ROOT (string): path to crispresso executables (for templates) + + Returns: + Nothin + """ + run_data = CRISPRessoShared.load_crispresso_info(crispresso_folder) + make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT) + + +def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT): + # dicts for each amplicon fig_names[amp_name] = [list of fig names] + # fig_locs[amp_name][fig_name] = figure location + # print('crispresso_report file: ' + crispresso_report_file + ' crispresso_folder : ' + crispresso_folder + ' root: ' + _ROOT) + figures = {'names': {}, 'locs': {}, 'titles': {}, 'captions': {}, 'datas': {}, 'htmls': {}, 'sgRNA_based_names': {}} + + def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, + amplicon_fig_names, amplicon_figures): + """ + Helper function to add figure if the file exists + if fig at filename exists, + amplicon_figs[figname] is set to that file + """ + # fullpath=os.path.join(crispresso_folder,fig_root+'.png') + pngfullpath = os.path.join(crispresso_folder, fig_root + '.png') + htmlfullpath = os.path.join(crispresso_folder, fig_root + '.html') + # print('adding file ' + fig_root + ' at ' + fullpath) + if os.path.exists(pngfullpath) or os.path.exists(htmlfullpath): + amplicon_fig_names.append(fig_name) + # amplicon_fig_locs[fig_name]=os.path.basename(fig_root+'.png') + amplicon_figures['locs'][fig_name] = os.path.basename(fig_root) + amplicon_figures['titles'][fig_name] = fig_title + amplicon_figures['captions'][fig_name] = fig_caption + amplicon_figures['datas'][fig_name] = [] + for (data_caption, data_file) in fig_data: + if os.path.exists(os.path.join(crispresso_folder, data_file)): + amplicon_figures['datas'][fig_name].append((data_caption, data_file)) + if os.path.exists(htmlfullpath): + with open(htmlfullpath) as html: + html_string = "
" + html_string += html.read() + html_string += "
" + amplicon_figures['htmls'][fig_name] = html_string + + global_fig_names = [] + for fig in ['1a', '1b', '1c', '1d', '5a', '6a', '8a', '11c']: + fig_name = 'plot_' + fig + if fig_name + '_root' in run_data['results']['general_plots']: + add_fig_if_exists(fig_name, run_data['results']['general_plots'][fig_name + '_root'], 'Figure ' + fig, + run_data['results']['general_plots'][fig_name + '_caption'], + run_data['results']['general_plots'][fig_name + '_data'], + global_fig_names, figures) + + amplicons = [] + for amplicon_name in run_data['results']['ref_names']: + amplicons.append(amplicon_name) + amplicon_figures = {'names': [], 'locs': {}, 'titles': {}, 'captions': {}, 'datas': {}} + + for fig in ['2a', '3a', '3b', '4a', '4b', '4c', '4d', '4e', '4f', '4g', '5', '6', '7', '8', '10a', '10b', '10c', + '11a']: + fig_name = 'plot_' + fig + if fig_name + '_root' in run_data['results']['refs'][amplicon_name]: + add_fig_if_exists(fig_name, run_data['results']['refs'][amplicon_name][fig_name + '_root'], + 'Figure ' + fig_name, + run_data['results']['refs'][amplicon_name][fig_name + '_caption'], + run_data['results']['refs'][amplicon_name][fig_name + '_data'], + global_fig_names, amplicon_figures) + + this_sgRNA_based_fig_names = {} + for fig in ['2b', '9', '10d', '10e', '10f', '10g', '11b']: + # fig 2b's + this_fig_names = [] + if 'plot_' + fig + '_roots' in run_data['results']['refs'][amplicon_name]: + for idx, plot_root in enumerate(run_data['results']['refs'][amplicon_name]['plot_' + fig + '_roots']): + fig_name = "plot_" + fig + "_" + str(idx) + add_fig_if_exists(fig_name, plot_root, 'Figure ' + fig_name + ' sgRNA ' + str(idx + 1), + run_data['results']['refs'][amplicon_name]['plot_' + fig + '_captions'][idx], + run_data['results']['refs'][amplicon_name]['plot_' + fig + '_datas'][idx], + this_fig_names, amplicon_figures) + this_sgRNA_based_fig_names[fig] = this_fig_names + + figures['names'][amplicon_name] = amplicon_figures['names'] + figures['sgRNA_based_names'][amplicon_name] = this_sgRNA_based_fig_names + + figures['locs'][amplicon_name] = amplicon_figures['locs'] + figures['titles'][amplicon_name] = amplicon_figures['titles'] + figures['captions'][amplicon_name] = amplicon_figures['captions'] + figures['datas'][amplicon_name] = amplicon_figures['datas'] + + report_display_name = "" + if run_data['running_info']['args'].name != "": + report_display_name = run_data['running_info']['args'].name + + # find path between the report and the data (if the report is in another directory vs in the same directory as the data) + crispresso_data_path = os.path.relpath(crispresso_folder, os.path.dirname(crispresso_report_file)) + if crispresso_data_path == ".": + crispresso_data_path = "" + else: + crispresso_data_path += "/" + + report_data = { + 'amplicons': amplicons, + 'figures': figures, + 'run_data': run_data, + 'report_display_name': report_display_name, + 'crispresso_data_path': crispresso_data_path, + } + + j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'templates'))) + template = j2_env.get_template('report.html') + + # dest_dir = os.path.dirname(crispresso_report_file) + # shutil.copy2(os.path.join(_ROOT,'templates','CRISPResso_justcup.png'),dest_dir) + # shutil.copy2(os.path.join(_ROOT,'templates','favicon.ico'),dest_dir) + + outfile = open(crispresso_report_file, 'w') + outfile.write(template.render(report_data=report_data)) + outfile.close() + + +def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info, batch_folder, _ROOT): + batch_names = crispresso2_info['results']['completed_batch_arr'] + display_names = crispresso2_info['results']['batch_input_names'] + + window_nuc_pct_quilts = crispresso2_info['results']['general_plots']['window_nuc_pct_quilt_plot_names'] + nuc_pct_quilts = crispresso2_info['results']['general_plots']['nuc_pct_quilt_plot_names'] + + window_nuc_conv_plots = crispresso2_info['results']['general_plots']['window_nuc_conv_plot_names'] + nuc_conv_plots = crispresso2_info['results']['general_plots']['nuc_conv_plot_names'] + + summary_plot_names = [] + if 'summary_plot_names' in crispresso2_info['results']['general_plots']: + summary_plot_names = crispresso2_info['results']['general_plots']['summary_plot_names'] + summary_plot_titles = {} + if 'summary_plot_titles' in crispresso2_info['results']['general_plots']: + summary_plot_titles = crispresso2_info['results']['general_plots']['summary_plot_titles'] + summary_plot_labels = {} + if 'summary_plot_labels' in crispresso2_info['results']['general_plots']: + summary_plot_labels = crispresso2_info['results']['general_plots']['summary_plot_labels'] + summary_plot_datas = {} + if 'summary_plot_datas' in crispresso2_info['results']['general_plots']: + summary_plot_datas = crispresso2_info['results']['general_plots']['summary_plot_datas'] + + allele_modification_heatmap_plot = {} + if 'allele_modification_heatmap_plot_names' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_names'] + else: + allele_modification_heatmap_plot['names'] = [] + if 'allele_modification_heatmap_plot_paths' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_paths'] + else: + allele_modification_heatmap_plot['paths'] = {} + if 'allele_modification_heatmap_plot_titles' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_titles'] + else: + allele_modification_heatmap_plot['titles'] = [] + if 'allele_modification_heatmap_plot_labels' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_labels'] + else: + allele_modification_heatmap_plot['labels'] = {} + if 'allele_modification_heatmap_plot_datas' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_datas'] + else: + allele_modification_heatmap_plot['datas'] = {} + + allele_modification_line_plot = {} + if 'allele_modification_line_plot_names' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_names'] + else: + allele_modification_line_plot['names'] = [] + if 'allele_modification_line_plot_paths' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_paths'] + else: + allele_modification_line_plot['paths'] = {} + if 'allele_modification_line_plot_titles' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_titles'] + else: + allele_modification_line_plot['titles'] = [] + if 'allele_modification_line_plot_labels' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_labels'] + else: + allele_modification_line_plot['labels'] = {} + if 'allele_modification_line_plot_datas' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_datas'] + else: + allele_modification_line_plot['datas'] = {} + + allele_modification_heatmap_plot['htmls'] = {} + for heatmap_plot_name, heatmap_plot_path in allele_modification_heatmap_plot['paths'].items(): + with open(heatmap_plot_path) as fh: + allele_modification_heatmap_plot['htmls'][heatmap_plot_name] = fh.read() + + allele_modification_line_plot['htmls'] = {} + for line_plot_name, line_plot_path in allele_modification_line_plot['paths'].items(): + with open(line_plot_path) as fh: + allele_modification_line_plot['htmls'][line_plot_name] = fh.read() + + #find path between the report and the data (if the report is in another directory vs in the same directory as the data) + crispresso_data_path = os.path.relpath(batch_folder, os.path.dirname(crispressoBatch_report_file)) + if crispresso_data_path == ".": + crispresso_data_path = "" + else: + crispresso_data_path += "/"; + + sub_html_files = {} + run_names = [] + for name in batch_names: + display_name = display_names[name] + sub_folder = 'CRISPResso_on_' + name + crispresso_folder = os.path.join(batch_folder, sub_folder) + run_data = CRISPRessoShared.load_crispresso_info(crispresso_folder) + if 'running_info' not in run_data: + raise Exception('CRISPResso run %s has no report. Cannot add to batch report.' % sub_folder) + + this_sub_html_file = sub_folder + ".html" + if run_data['running_info']['args'].place_report_in_output_folder: + this_sub_html_file = os.path.join(sub_folder, run_data['running_info']['report_filename']) + sub_html_files[display_name] = this_sub_html_file + + run_names.append(display_name) + + output_title = 'CRISPResso Batch Output' + if crispresso2_info['running_info']['args'].name != '': + output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) + + make_multi_report( + run_names, + sub_html_files, + crispressoBatch_report_file, + batch_folder, + _ROOT, + output_title, + summary_plots={ + 'names': summary_plot_names, + 'titles': summary_plot_titles, + 'labels': summary_plot_labels, + 'datas': summary_plot_datas, + }, + window_nuc_pct_quilts=window_nuc_pct_quilts, + nuc_pct_quilts=nuc_pct_quilts, + window_nuc_conv_plots=window_nuc_conv_plots, + nuc_conv_plots=nuc_conv_plots, + allele_modification_heatmap_plot=allele_modification_heatmap_plot, + allele_modification_line_plot=allele_modification_line_plot, + ) + + +def make_pooled_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): + names_arr = crispresso2_info['results']['good_region_names'] + output_title = 'CRISPResso Pooled Output' + if crispresso2_info['running_info']['args'].name != '': + output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT) + + +def make_compare_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): + names_arr = [] + output_title = 'CRISPResso Compare Output' + if crispresso2_info['running_info']['args'].name != '': + output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT) + + +def make_meta_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): + names_arr = crispresso2_info['meta_names_arr'] + input_names = crispresso2_info['meta_input_names'] + output_title = 'CRISPresso Meta Output' + if crispresso2_info['running_info']['args'].name != '': + output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, + display_names=input_names) + + +def make_wgs_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): + names_arr = crispresso2_info['results']['good_region_names'] + output_title = 'CRISPResso WGS Output' + if crispresso2_info['running_info']['args'].name != '': + output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT) + + +def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, crispresso_report_file, folder, _ROOT, + display_names=None): + """ + Prepares information to make a report of multiple CRISPResso runs - like CRISPRessoWGS or CRISPRessoPooled + + Parameters: + crispresso2_info (dict): information from the crispresso multi run + names_arr (arr of strings): Names of the crispresso runs + report_name (string): text to be shown at top of report + crispresso_report_file (string): path to write report to + folder (string): folder containing crispresso runs + _ROOT (string): location of crispresso assets (images, templates, etc) + display_names (dict): report_name->display_name; Titles to be shown for crispresso runs (if different from names_arr, e.g. if display_names have spaces or bad chars, they won't be the same as names_arr) + + Returns: + Nothin + """ + + summary_plot_names = [] + if 'summary_plot_names' in crispresso2_info['results']['general_plots']: + summary_plot_names = crispresso2_info['results']['general_plots']['summary_plot_names'] + summary_plot_titles = {} + if 'summary_plot_titles' in crispresso2_info['results']['general_plots']: + summary_plot_titles = crispresso2_info['results']['general_plots']['summary_plot_titles'] + summary_plot_labels = {} + if 'summary_plot_labels' in crispresso2_info['results']['general_plots']: + summary_plot_labels = crispresso2_info['results']['general_plots']['summary_plot_labels'] + summary_plot_datas = {} + if 'summary_plot_datas' in crispresso2_info['results']['general_plots']: + summary_plot_datas = crispresso2_info['results']['general_plots']['summary_plot_datas'] + + run_names = [] + sub_html_files = {} + sub_2a_labels = {} + sub_2a_pdfs = {} + + for name in names_arr: + display_name = name + if display_names is not None: + display_name = display_names[name] + + folder_name = 'CRISPResso_on_%s' % name + sub_folder = os.path.join(folder, folder_name) + run_data = CRISPRessoShared.load_crispresso_info(sub_folder) + if 'running_info' not in run_data: + raise Exception('CRISPResso run %s has no report. Cannot add to report.' % sub_folder) + + run_names.append(display_name) + + this_sub_html_file = os.path.basename(folder_name) + ".html" + if run_data['running_info']['args'].place_report_in_output_folder: + this_sub_html_file = os.path.join(os.path.basename(sub_folder), run_data['running_info']['report_filename']) + sub_html_files[display_name] = this_sub_html_file + + this_sub_2a_labels = [] + this_sub_2a_pdfs = [] + for ref_name in run_data['results']['ref_names']: + if 'plot_2a_root' in run_data['results']['refs'][ref_name]: + pdf_file = run_data['results']['refs'][ref_name]['plot_2a_root'] + ".pdf" + if os.path.exists(pdf_file): + this_sub_2a_pdfs.append(run_data['results']['refs'][ref_name]['plot_2a_root'] + ".pdf") + this_sub_2a_labels.append("Nucleotide distribution across " + ref_name) + + sub_2a_labels[display_name] = this_sub_2a_labels + sub_2a_pdfs[display_name] = this_sub_2a_pdfs + + make_multi_report( + run_names, + sub_html_files, + crispresso_report_file, + folder, + _ROOT, + report_name, + summary_plots={ + 'names': summary_plot_names, + 'titles': summary_plot_titles, + 'labels': summary_plot_labels, + 'datas': summary_plot_datas, + }, + ) + + +def make_multi_report( + run_names, + sub_html_files, + crispresso_multi_report_file, + crispresso_folder, + _ROOT, + report_name, + window_nuc_pct_quilts=[], + nuc_pct_quilts=[], + window_nuc_conv_plots=[], + nuc_conv_plots=[], + summary_plots={ + 'names': [], + 'titles': [], + 'labels': [], + 'datas': [], + }, + compact_plots_to_show={}, + allele_modification_heatmap_plot={}, + allele_modification_line_plot={}, +): + """ + Makes an HTML report for a run containing multiple crispresso runs + + Parameters: + run_names (arr of strings): names of runs + sub_html_files (dict): dict of run_name->file_loc + crispresso_multi_report_file (string): path of file to write to + report_name (string): description of report type to be shown at top of report + crispresso_folder (string): absolute path to the crispresso output + _ROOT (string): absolute path to the crispresso executable + +<<<<<<< HEAD + summary_plot (dict): a dict with the following keys: +======= + summary_plots (dict): a dict with the following keys: +>>>>>>> origin/master + names (list): list of plot names - keys for following dicts + titles (dict): dict of plot_name->plot_title + labels (dict): dict of plot_name->plot_label + datas (dict): dict of plot_name->[(datafile_description, data_filename), ...] + compact_plots_to_show (dict): name=>{'href': path to target(report) when user clicks on image, 'img': path to png image to show} + allele_modification_heatmap_plot (dict): a dict with the following keys: + names (list): list of plot names for heatmaps, keys for dicts below + htmls (dict): dict of plot_name->HTML for the plot + titles (dict): dict of plot_name->plot_title + labels (dict): dict of plot_name->plot_label + datas (dict): dict of plot_name->[(datafile_description, data_filename), ...] + """ + + def dirname(path): + return os.path.basename(os.path.dirname(path)) + + def fill_default(dictionary, key, default_type=list): + if key not in dictionary: + dictionary[key] = default_type() + + j2_env = Environment( + loader=FileSystemLoader(os.path.join(_ROOT, 'templates')), + ) + j2_env.filters['dirname'] = dirname + template = j2_env.get_template('multiReport.html') + + crispresso_data_path = os.path.relpath( + crispresso_folder, os.path.dirname(crispresso_multi_report_file), + ) + if crispresso_data_path == ".": + crispresso_data_path = "" + else: + crispresso_data_path += "/" + + dictionaries = [ + allele_modification_heatmap_plot, allele_modification_line_plot, + ] + keys_and_default_types = [ + ('names', list), + ('htmls', dict), + ('titles', list), + ('labels', dict), + ('datas', dict), + ] + for dictionary in dictionaries: + for key, default_type in keys_and_default_types: + fill_default( + dictionary, + key, + default_type, + ) + + with open(crispresso_multi_report_file, 'w') as outfile: + outfile.write(template.render( + window_nuc_pct_quilts=window_nuc_pct_quilts, + nuc_pct_quilts=nuc_pct_quilts, + window_nuc_conv_plots=window_nuc_conv_plots, + nuc_conv_plots=nuc_conv_plots, + crispresso_data_path=crispresso_data_path, + summary_plot_names=summary_plots['names'], + summary_plot_titles=summary_plots['titles'], + summary_plot_labels=summary_plots['labels'], + summary_plot_datas=summary_plots['datas'], + run_names=run_names, + sub_html_files=sub_html_files, + report_name=report_name, + compact_plots_to_show=compact_plots_to_show, + allele_modification_heatmap_plot_names=allele_modification_heatmap_plot['names'], + allele_modification_heatmap_plot_htmls=allele_modification_heatmap_plot['htmls'], + allele_modification_heatmap_plot_titles=allele_modification_heatmap_plot['titles'], + allele_modification_heatmap_plot_labels=allele_modification_heatmap_plot['labels'], + allele_modification_heatmap_plot_datas=allele_modification_heatmap_plot['datas'], + allele_modification_line_plot_names=allele_modification_line_plot['names'], + allele_modification_line_plot_htmls=allele_modification_line_plot['htmls'], + allele_modification_line_plot_titles=allele_modification_line_plot['titles'], + allele_modification_line_plot_labels=allele_modification_line_plot['labels'], + allele_modification_line_plot_datas=allele_modification_line_plot['datas'], + )) + + +def make_aggregate_report( + crispresso2_info, + report_name, + crispresso_report_file, + crispresso_report_folder, + _ROOT, + folder_arr, + crispresso_html_reports, + compact_plots_to_show={}, + display_names=None, +): + """ + Prepares information to make a report of a CRISPRessoAggregate run + + Parameters: + crispresso2_info (dict): information from the crispresso aggregate run + report_name (string): text to be shown at top of report + crispresso_report_file (string): path to write report to + crispresso_report_folder (string): path containing aggregated plots, etc. + _ROOT (string): location of crispresso assets (images, templates, etc) + folder_arr (arr of strings): paths to the aggregated crispresso folders + crispresso_html_reports (dict): folder->html_path; Paths to the aggregated crispresso run html reports + compact_plots_to_show (dict): name=>{'href': path to target(report) when user clicks on image, 'img': path to png image to show} + display_names (dict): folder->display_name; Titles to be shown for crispresso runs (if different from names_arr, e.g. if display_names have spaces or bad chars, they won't be the same as names_arr) + + Returns: + Nothin + """ + summary_plots = {} + if 'summary_plot_names' in crispresso2_info['results']['general_plots']: + summary_plots['names'] = crispresso2_info['results']['general_plots']['summary_plot_names'] + else: + summary_plots['names'] = [] + if 'summary_plot_titles' in crispresso2_info['results']['general_plots']: + summary_plots['titles'] = crispresso2_info['results']['general_plots']['summary_plot_titles'] + else: + summary_plots['titles'] = {} + if 'summary_plot_labels' in crispresso2_info['results']['general_plots']: + summary_plots['labels'] = crispresso2_info['results']['general_plots']['summary_plot_labels'] + else: + summary_plots['labels'] = {} + if 'summary_plot_datas' in crispresso2_info['results']['general_plots']: + summary_plots['datas'] = crispresso2_info['results']['general_plots']['summary_plot_datas'] + else: + summary_plots['datas'] = {} + + allele_modification_heatmap_plot = {} + if 'allele_modification_heatmap_plot_names' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_names'] + else: + allele_modification_heatmap_plot['names'] = [] + if 'allele_modification_heatmap_plot_paths' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_paths'] + else: + allele_modification_heatmap_plot['paths'] = {} + if 'allele_modification_heatmap_plot_titles' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_titles'] + else: + allele_modification_heatmap_plot['titles'] = {} + if 'allele_modification_heatmap_plot_labels' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_labels'] + else: + allele_modification_heatmap_plot['labels'] = {} + if 'allele_modification_heatmap_plot_datas' in crispresso2_info['results']['general_plots']: + allele_modification_heatmap_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_datas'] + else: + allele_modification_heatmap_plot['datas'] = {} + + allele_modification_line_plot = {} + if 'allele_modification_line_plot_names' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_names'] + else: + allele_modification_line_plot['names'] = [] + if 'allele_modification_line_plot_paths' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_paths'] + else: + allele_modification_line_plot['paths'] = {} + if 'allele_modification_line_plot_titles' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_titles'] + else: + allele_modification_line_plot['titles'] = {} + if 'allele_modification_line_plot_labels' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_labels'] + else: + allele_modification_line_plot['labels'] = {} + if 'allele_modification_line_plot_datas' in crispresso2_info['results']['general_plots']: + allele_modification_line_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_datas'] + else: + allele_modification_line_plot['datas'] = {} + + window_nuc_pct_quilts = [] + if 'window_nuc_pct_quilt_plot_names' in crispresso2_info['results']['general_plots']: + window_nuc_pct_quilts = crispresso2_info['results']['general_plots']['window_nuc_pct_quilt_plot_names'] + nuc_pct_quilts = [] + if 'nuc_pct_quilt_plot_names' in crispresso2_info['results']['general_plots']: + nuc_pct_quilts = crispresso2_info['results']['general_plots']['nuc_pct_quilt_plot_names'] + + run_names = [] + sub_html_files = {} + + for idx, folder in enumerate(folder_arr): + display_name = folder + if display_names is not None: + display_name = display_names[folder] + + run_names.append(display_name) + sub_html_file = os.path.relpath(crispresso_html_reports[folder], crispresso_report_folder) + sub_html_files[display_name] = sub_html_file + + for compact_plot in compact_plots_to_show: + old_href = compact_plots_to_show[compact_plot]['href'] + compact_plots_to_show[compact_plot]['href'] = os.path.relpath(old_href, crispresso_report_folder) + old_img = compact_plots_to_show[compact_plot]['img'] + compact_plots_to_show[compact_plot]['img'] = os.path.relpath(old_img, crispresso_report_folder) + + allele_modification_heatmap_plot['htmls'] = {} + for heatmap_plot_name, heatmap_plot_path in allele_modification_heatmap_plot['paths'].items(): + with open(heatmap_plot_path) as fh: + allele_modification_heatmap_plot['htmls'][heatmap_plot_name] = fh.read() + + allele_modification_line_plot['htmls'] = {} + for line_plot_name, line_plot_path in allele_modification_line_plot['paths'].items(): + with open(line_plot_path) as fh: + allele_modification_line_plot['htmls'][line_plot_name] = fh.read() + + make_multi_report( + run_names, + sub_html_files, + crispresso_report_file, + crispresso_report_folder, + _ROOT, + report_name, + window_nuc_pct_quilts=window_nuc_pct_quilts, + nuc_pct_quilts=nuc_pct_quilts, + summary_plots=summary_plots, + compact_plots_to_show=compact_plots_to_show, + allele_modification_heatmap_plot=allele_modification_heatmap_plot, + allele_modification_line_plot=allele_modification_line_plot, + ) diff --git a/templates/CRISPResso_justcup.png b/templates/CRISPResso_justcup.png new file mode 100644 index 0000000000000000000000000000000000000000..3116c48c394f23cf37669c6dbb92928ef0d88b9d GIT binary patch literal 42782 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 literal 0 HcmV?d00001 diff --git a/templates/favicon.ico b/templates/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8aed2d0743b52f12c1f0f8b2b4c439ba77091af3 GIT binary patch literal 1150 zcmbVMTWeE65MIGIUy2Vt`{*xIQTtGpYE@zjwT6~P+tO3xNz+rB6BBFO#3;0l0Sg5a zZAl=|kQxgi_XiV_ko)E9&Xx@^1Pab!cV@nwZ)Rt5au~b9pOF#9_nYkQRmN^G#%}S& zA&y+&TrtMau3x)Y!si1jMS7+{#1gs$u8 zbUGr3j2X-&@p8G0S4Jb0RSQPWS&7j;UxRtyjV~aI9)ri>NaQ} z>~Oeuu(+b&=h3fA`*^3SaBOd3!|A}9U5943;giRWWz~!c!wYD(4dnBAQA^%g>LQ<) zs%h}-?+MOFw+owmecsy@dCWZbuGb5@(>av?=j;rMMTMfi$Kz)c7#knQqo+?`G?`%A zbYkx98F-lC8jXMI_VcApG3|C6>2zAuA-}}uB7YyLWxUk& zdL5Ze2Dw~LK*?khg+c+OoBUm*vs5Z2Y{?-l?@je8m5Ml`8pI$zXSiP&jEy + + + CRISPResso2 Report + + + + + + + + + + + + + + + + + + + {% block head %}{% endblock %} + + + + +
+ +
+
+
+
+
+

CRISPResso2

+

Analysis of genome editing outcomes from deep sequencing data

+
+
+ +
+
+ +
+ {% block content %}{% endblock %} + +
+ +
+ + +
+ +
+ + + + + + + + + {% block foot %}{% endblock %} + + + diff --git a/templates/multiReport.html b/templates/multiReport.html new file mode 100644 index 00000000..4f346efe --- /dev/null +++ b/templates/multiReport.html @@ -0,0 +1,285 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+ +
+
+ + {% if run_names|length > 0 %} +
+
+
{{report_name}}
+
+
+
+ {% for run_name in run_names %} + {{run_name}} + {% endfor %} +
+
+
+ {% endif %} + + {% if window_nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages around guides
+
+
+ {% for plot_name in window_nuc_pct_quilts %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages in the entire amplicon
+
+
+ {% for plot_name in nuc_pct_quilts %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if window_nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases around guides
+
+
+ {% for plot_name in window_nuc_conv_plots %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases in the entire amplicon
+
+
+ {% for plot_name in nuc_conv_plots %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if summary_plot_names|length > 0 %} + {% for plot_name in summary_plot_names %} +
+
+
{{summary_plot_titles[plot_name]}}
+
+
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endfor %} + {% endif %} + + {% if allele_modification_heatmap_plot_names|length > 0 %} + {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} + {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} + {% set modification_type = heatmap_plot_name.split('_')[3] %} +
+
+
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
+ +
+
+
+
+ {{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} + + {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {{allele_modification_line_plot_htmls[line_plot_name]}} + + {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+
+
+ + {% endfor %} + + + + {% endif %} + + {% if compact_plots_to_show|length > 0 %} +
+
+
Summary Plots
+
+
+
+ {% for compact_plot in compact_plots_to_show %} + + {% endfor %} +
+
+
+ {% endif %} + + +
+ +
+ +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+{% endblock %} + +{% block foot %} +{% endblock %} diff --git a/templates/report.html b/templates/report.html new file mode 100644 index 00000000..ff274edd --- /dev/null +++ b/templates/report.html @@ -0,0 +1,854 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+ +
+
+ +
+
+ {% if report_data['report_display_name'] != '' %} +
{{report_data['report_display_name']}}
+ {% endif %} +
CRISPResso2 run information
+ +
+
+
+
+ {{report_data['figures']['htmls']['plot_1a']}} + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_1a'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

+

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

+

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

+ {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} +

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

+ {% endif %} +

Command used:

{{report_data['run_data']['running_info']['command_used']}}

+

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

+

Running log

+
+
+
+
+ +
+
+
Allele assignments
+ +
+
+
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_1b'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_1c'] %} +

Data: {{data_label}}

+ {% endfor %} +
+ {% if report_data['figures']['locs']['plot_1d'] %} +
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_1d'] %} +

Data: {{data_label}}

+ {% endfor %} +
+ {% endif %} +
+ +
+
{# end card #} + + {# start global coding sequence report #} + {% if report_data['figures']['locs']['plot_5a'] %} +
+
+
Global frameshift analysis
+
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_5a'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endif %} + + {% if report_data['figures']['locs']['plot_6a'] %} +
+
+
Global frameshift mutagenesis profiles
+
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_6a'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endif %} + + {% if report_data['figures']['locs']['plot_8a'] %} +
+
+
Global splicing analysis
+
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_8a'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endif %} + {# end of global coding sequence analysis #} + + {# start hdr summary #} + {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
HDR summary plot
+ {% else %} +
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas'][report_data.amplicons[0]]['plot_4g'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endif %} + {# end HDR summary #} + + {# start prime editing report #} + {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
Prime editing report
+ {% else %} +
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas'][report_data.amplicons[0]]['plot_11a'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endif %} + + {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
Prime editing summary plots at analysis positions
+ {% else %} +
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} +
+ + + {% for (data_label,data_path) in report_data['figures']['datas'][report_data.amplicons[0]][fig_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+ {% endfor %} +
+
+ {% endif %} {# end plot 11b for prime editing #} + + {% if report_data['figures']['locs']['plot_11c'] %} +
+
+
Scaffold insertions
+
+
+ + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_11c'] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endif %} + + {# end prime editing section #} + + + {% if report_data.amplicons|length == 1 %} +
{# if only one amplicon, just a normal div #} + {% else %} + {# If there is more than one amplicon, print a navigation to show each amplicon #} +

Reads are aligned to each amplicon sequence separately. Quantification and visualization of these reads are shown for each amplicon below:

+
+
+
Amplicons
+ +
+ {% endif %} {# end if report contains more than one amplicon #} + + + {% if report_data.amplicons|length == 1 %} {# if only one amplicon, just a normal div #} +
+ {% else %} + {# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+{% endblock %} + +{% block foot %} + +{% endblock %} From 08fcd4eda347886e66c4d2a170eb03b00a02781a Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Tue, 17 May 2022 10:08:08 -0600 Subject: [PATCH 02/33] Web updates refactoring done --- CRISPRessoReport.py | 113 ++++++++++++---------- templates/batchReport.html | 183 ++++++++++++++++++++++++++++++++++++ templates/layout.html | 176 +++++++++++++++++++++++++++++----- templates/pooledReport.html | 105 +++++++++++++++++++++ templates/report.html | 2 +- templates/wgsReport.html | 103 ++++++++++++++++++++ 6 files changed, 609 insertions(+), 73 deletions(-) create mode 100644 templates/batchReport.html create mode 100644 templates/pooledReport.html create mode 100644 templates/wgsReport.html diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py index a49f2584..aa3d87c9 100644 --- a/CRISPRessoReport.py +++ b/CRISPRessoReport.py @@ -25,39 +25,37 @@ def make_report_from_folder(crispresso_report_file, crispresso_folder, _ROOT): make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT) -def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT): - # dicts for each amplicon fig_names[amp_name] = [list of fig names] - # fig_locs[amp_name][fig_name] = figure location - # print('crispresso_report file: ' + crispresso_report_file + ' crispresso_folder : ' + crispresso_folder + ' root: ' + _ROOT) - figures = {'names': {}, 'locs': {}, 'titles': {}, 'captions': {}, 'datas': {}, 'htmls': {}, 'sgRNA_based_names': {}} - - def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, - amplicon_fig_names, amplicon_figures): +def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, + amplicon_fig_names, amplicon_figures, crispresso_folder): + """ + Helper function to add figure if the file exists + if fig at filename exists, + amplicon_figs[figname] is set to that file """ - Helper function to add figure if the file exists - if fig at filename exists, - amplicon_figs[figname] is set to that file - """ - # fullpath=os.path.join(crispresso_folder,fig_root+'.png') - pngfullpath = os.path.join(crispresso_folder, fig_root + '.png') - htmlfullpath = os.path.join(crispresso_folder, fig_root + '.html') - # print('adding file ' + fig_root + ' at ' + fullpath) - if os.path.exists(pngfullpath) or os.path.exists(htmlfullpath): - amplicon_fig_names.append(fig_name) - # amplicon_fig_locs[fig_name]=os.path.basename(fig_root+'.png') - amplicon_figures['locs'][fig_name] = os.path.basename(fig_root) - amplicon_figures['titles'][fig_name] = fig_title - amplicon_figures['captions'][fig_name] = fig_caption - amplicon_figures['datas'][fig_name] = [] - for (data_caption, data_file) in fig_data: - if os.path.exists(os.path.join(crispresso_folder, data_file)): - amplicon_figures['datas'][fig_name].append((data_caption, data_file)) - if os.path.exists(htmlfullpath): - with open(htmlfullpath) as html: - html_string = "
" - html_string += html.read() - html_string += "
" - amplicon_figures['htmls'][fig_name] = html_string + # fullpath=os.path.join(crispresso_folder,fig_root+'.png') + pngfullpath = os.path.join(crispresso_folder, fig_root + '.png') + htmlfullpath = os.path.join(crispresso_folder, fig_root + '.html') + # print('adding file ' + fig_root + ' at ' + fullpath) + if os.path.exists(pngfullpath) or os.path.exists(htmlfullpath): + amplicon_fig_names.append(fig_name) + # amplicon_fig_locs[fig_name]=os.path.basename(fig_root+'.png') + amplicon_figures['locs'][fig_name] = os.path.basename(fig_root) + amplicon_figures['titles'][fig_name] = fig_title + amplicon_figures['captions'][fig_name] = fig_caption + amplicon_figures['datas'][fig_name] = [] + for (data_caption, data_file) in fig_data: + if os.path.exists(os.path.join(crispresso_folder, data_file)): + amplicon_figures['datas'][fig_name].append((data_caption, data_file)) + if os.path.exists(htmlfullpath): + with open(htmlfullpath) as html: + html_string = "
" + html_string += html.read() + html_string += "
" + amplicon_figures['htmls'][fig_name] = html_string + + +def assemble_figs(run_data, crispresso_folder): + figures = {'names': {}, 'locs': {}, 'titles': {}, 'captions': {}, 'datas': {}, 'htmls': {}, 'sgRNA_based_names': {}} global_fig_names = [] for fig in ['1a', '1b', '1c', '1d', '5a', '6a', '8a', '11c']: @@ -66,7 +64,7 @@ def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, add_fig_if_exists(fig_name, run_data['results']['general_plots'][fig_name + '_root'], 'Figure ' + fig, run_data['results']['general_plots'][fig_name + '_caption'], run_data['results']['general_plots'][fig_name + '_data'], - global_fig_names, figures) + global_fig_names, figures, crispresso_folder) amplicons = [] for amplicon_name in run_data['results']['ref_names']: @@ -81,7 +79,7 @@ def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, 'Figure ' + fig_name, run_data['results']['refs'][amplicon_name][fig_name + '_caption'], run_data['results']['refs'][amplicon_name][fig_name + '_data'], - global_fig_names, amplicon_figures) + global_fig_names, amplicon_figures, crispresso_folder) this_sgRNA_based_fig_names = {} for fig in ['2b', '9', '10d', '10e', '10f', '10g', '11b']: @@ -93,7 +91,7 @@ def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, add_fig_if_exists(fig_name, plot_root, 'Figure ' + fig_name + ' sgRNA ' + str(idx + 1), run_data['results']['refs'][amplicon_name]['plot_' + fig + '_captions'][idx], run_data['results']['refs'][amplicon_name]['plot_' + fig + '_datas'][idx], - this_fig_names, amplicon_figures) + this_fig_names, amplicon_figures, crispresso_folder) this_sgRNA_based_fig_names[fig] = this_fig_names figures['names'][amplicon_name] = amplicon_figures['names'] @@ -103,6 +101,15 @@ def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, figures['titles'][amplicon_name] = amplicon_figures['titles'] figures['captions'][amplicon_name] = amplicon_figures['captions'] figures['datas'][amplicon_name] = amplicon_figures['datas'] + data = {'amplicons': amplicons, 'figures': figures} + return data + + +def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, web_version=False): + # dicts for each amplicon fig_names[amp_name] = [list of fig names] + # fig_locs[amp_name][fig_name] = figure location + # print('crispresso_report file: ' + crispresso_report_file + ' crispresso_folder : ' + crispresso_folder + ' root: ' + _ROOT) + data = assemble_figs(run_data, crispresso_folder) report_display_name = "" if run_data['running_info']['args'].name != "": @@ -116,8 +123,8 @@ def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, crispresso_data_path += "/" report_data = { - 'amplicons': amplicons, - 'figures': figures, + 'amplicons': data['amplicons'], + 'figures': data['figures'], 'run_data': run_data, 'report_display_name': report_display_name, 'crispresso_data_path': crispresso_data_path, @@ -247,6 +254,7 @@ def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info, batch_folder, _ROOT, output_title, + 'batch', summary_plots={ 'names': summary_plot_names, 'titles': summary_plot_titles, @@ -267,7 +275,7 @@ def make_pooled_report_from_folder(crispresso_report_file, crispresso2_info, fol output_title = 'CRISPResso Pooled Output' if crispresso2_info['running_info']['args'].name != '': output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'pooled') def make_compare_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): @@ -275,7 +283,7 @@ def make_compare_report_from_folder(crispresso_report_file, crispresso2_info, fo output_title = 'CRISPResso Compare Output' if crispresso2_info['running_info']['args'].name != '': output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'compare') def make_meta_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): @@ -284,7 +292,7 @@ def make_meta_report_from_folder(crispresso_report_file, crispresso2_info, folde output_title = 'CRISPresso Meta Output' if crispresso2_info['running_info']['args'].name != '': output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'meta', display_names=input_names) @@ -293,10 +301,10 @@ def make_wgs_report_from_folder(crispresso_report_file, crispresso2_info, folder output_title = 'CRISPResso WGS Output' if crispresso2_info['running_info']['args'].name != '': output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT) + make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'wgs') -def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, crispresso_report_file, folder, _ROOT, +def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, crispresso_report_file, folder, _ROOT, crispresso_tool, display_names=None): """ Prepares information to make a report of multiple CRISPResso runs - like CRISPRessoWGS or CRISPRessoPooled @@ -369,6 +377,7 @@ def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, cris folder, _ROOT, report_name, + crispresso_tool, summary_plots={ 'names': summary_plot_names, 'titles': summary_plot_titles, @@ -385,6 +394,7 @@ def make_multi_report( crispresso_folder, _ROOT, report_name, + crispresso_tool, window_nuc_pct_quilts=[], nuc_pct_quilts=[], window_nuc_conv_plots=[], @@ -409,12 +419,7 @@ def make_multi_report( report_name (string): description of report type to be shown at top of report crispresso_folder (string): absolute path to the crispresso output _ROOT (string): absolute path to the crispresso executable - -<<<<<<< HEAD - summary_plot (dict): a dict with the following keys: -======= summary_plots (dict): a dict with the following keys: ->>>>>>> origin/master names (list): list of plot names - keys for following dicts titles (dict): dict of plot_name->plot_title labels (dict): dict of plot_name->plot_label @@ -439,7 +444,14 @@ def fill_default(dictionary, key, default_type=list): loader=FileSystemLoader(os.path.join(_ROOT, 'templates')), ) j2_env.filters['dirname'] = dirname - template = j2_env.get_template('multiReport.html') + if crispresso_tool == 'batch': + template = j2_env.get_template('batchReport.html') + elif crispresso_tool == 'pooled': + template = j2_env.get_template('pooledReport.html') + elif crispresso_tool == 'wgs': + template = j2_env.get_template('wgsReport.html') + else: + template = j2_env.get_template('multiReport.html') crispresso_data_path = os.path.relpath( crispresso_folder, os.path.dirname(crispresso_multi_report_file), @@ -466,7 +478,10 @@ def fill_default(dictionary, key, default_type=list): key, default_type, ) - + web = False + if not web: + for html in sub_html_files: + sub_html_files[html] = crispresso_data_path + sub_html_files[html] with open(crispresso_multi_report_file, 'w') as outfile: outfile.write(template.render( window_nuc_pct_quilts=window_nuc_pct_quilts, diff --git a/templates/batchReport.html b/templates/batchReport.html new file mode 100644 index 00000000..10b4e4e2 --- /dev/null +++ b/templates/batchReport.html @@ -0,0 +1,183 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+ +
+
+ + {% if run_names|length > 0 %} +
+
+
{{report_name}}
+
+
+
+ {% for run_name in run_names %} + {{run_name}} + {% endfor %} +
+
+
+ {% endif %} + + {% if window_nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages around guides
+
+
+ {% for plot_name in window_nuc_pct_quilts %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages in the entire amplicon
+
+
+ {% for plot_name in nuc_pct_quilts %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if window_nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases around guides
+
+
+ {% for plot_name in window_nuc_conv_plots %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases in the entire amplicon
+
+
+ {% for plot_name in nuc_conv_plots %} +
{{summary_plot_titles[plot_name]}}
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endfor %} +
+
+ {% endif %} + + {% if summary_plot_names|length > 0 %} + {% for plot_name in summary_plot_names %} +
+
+
{{summary_plot_titles[plot_name]}}
+
+
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endfor %} + {% endif %} + + +
+ +
+ + + + {# data bit for web version: #} + {# +

Data: {{data_label}}

+ #} +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+
+{% endblock %} + +{% block foot %} +{% endblock %} diff --git a/templates/layout.html b/templates/layout.html index 5eba4687..05a1e959 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -1,20 +1,36 @@ - CRISPResso2 Report + CRISPResso2 - - + + + + + + + + + @@ -39,65 +71,163 @@ Remove this if you use the .htaccess --> - - - + + + + + {% block head %}{% endblock %} -
- +
+ {{ self.help_block() }} +
+ {% if get_flashed_messages != null %} + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} + {% if category == "error" %} + + {% else %} + + {% endif %} + {% endfor %} + {% endif %} + {% endwith %} + {% endif %} + + {# if default user (normal crispresso mode) #} + {% if current_user != null and not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} + +
-
+
-

CRISPResso2

-

Analysis of genome editing outcomes from deep sequencing data

+

CRISPResso2

+

Analysis of genome editing outcomes from deep sequencing data

-
-
- {% block content %}{% endblock %} + {% else %} + {# if doing user sessions #} + +
+ {% endif %} + +
+
+
+
+ {% block help_block %} {% endblock %} +
+
+
-
+ {% block content %}{% endblock %} + {% if current_user != null and not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} +
+
+ {% else %} +
+
+ +
+
+ {% endif %} + - - - + {% block foot %}{% endblock %} diff --git a/templates/pooledReport.html b/templates/pooledReport.html new file mode 100644 index 00000000..9ae88cc6 --- /dev/null +++ b/templates/pooledReport.html @@ -0,0 +1,105 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+ +
+
+ + {% if run_names|length > 0 %} + + {% endif %} + + {% if summary_plot_names|length > 0 %} + {% for plot_name in summary_plot_names %} +
+
+
{{summary_plot_titles[plot_name]}}
+
+
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endfor %} + {% endif %} + + + {# data bit for web version: #} + {# +

Data: {{data_label}}

+ #} +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+
+{% endblock %} + +{% block foot %} +{% endblock %} diff --git a/templates/report.html b/templates/report.html index ff274edd..50e0868b 100644 --- a/templates/report.html +++ b/templates/report.html @@ -75,7 +75,7 @@
CRISPResso2 run information
- {{report_data['figures']['htmls']['plot_1a']}} + {{report_data['figures']['htmls']['plot_1a']|safe}} {% for (data_label,data_path) in report_data['figures']['datas']['plot_1a'] %}

Data: {{data_label}}

diff --git a/templates/wgsReport.html b/templates/wgsReport.html new file mode 100644 index 00000000..3cf2c781 --- /dev/null +++ b/templates/wgsReport.html @@ -0,0 +1,103 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+ +
+
+ +
+
+
{{report_name}}
+
+
+
+ {% for region_name in run_names %} + {{region_name}} + {% endfor %} +
+
+
+ + {% if summary_plot_names|length > 0 %} + {% for plot_name in summary_plot_names %} +
+
+
{{summary_plot_titles[plot_name]}}
+
+
+ + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {% endfor %} + {% endif %} + + + {# data bit for web version: #} + {# +

Data: {{data_label}}

+ #} +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+
+{% endblock %} + +{% block foot %} +{% endblock %} From ee721b37a97155da72d5cddba01bfded58461748 Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Wed, 29 Jun 2022 23:19:05 -0600 Subject: [PATCH 03/33] Add function to render template partials without using Flask --- CRISPRessoReport.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py index aa3d87c9..c115ae69 100644 --- a/CRISPRessoReport.py +++ b/CRISPRessoReport.py @@ -6,9 +6,41 @@ import os from jinja2 import Environment, FileSystemLoader +from jinja_partials import generate_render_partial, render_partial from CRISPResso2 import CRISPRessoShared +def render_template(template_name, jinja2_env, **data): + """Render a template with partials. + + Parameters + ---------- + template_name: str + The name of the template to render. For example, if you have a template + file called `templates/my_template.html` you would pass in + `my_template.html`. + jinja2_env: jinja2.Environment + The Jinja2 environment being used. + **data: keyword arguments of any type + Additional keyword arguments that are passed to the template. + + Returns + ------- + The rendered template. + """ + def custom_partial_render(partial_template_name, **partial_data): + template = jinja2_env.get_template(partial_template_name) + partial_data.update( + render_partial=generate_render_partial( + custom_partial_render, + ), + ) + return template.render(**partial_data) + return render_partial( + template_name, custom_partial_render, **data, + ) + + def make_report_from_folder(crispresso_report_file, crispresso_folder, _ROOT): """ Makes an html report for a crispresso run @@ -131,6 +163,7 @@ def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, web_ } j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'templates'))) + breakpoint() template = j2_env.get_template('report.html') # dest_dir = os.path.dirname(crispresso_report_file) From 84e0969968218bf74478a62754370937f1bc7312 Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Wed, 29 Jun 2022 23:42:26 -0600 Subject: [PATCH 04/33] Use the `render_template` function for each report --- CRISPRessoReport.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py index c115ae69..1cc809b2 100644 --- a/CRISPRessoReport.py +++ b/CRISPRessoReport.py @@ -163,16 +163,15 @@ def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, web_ } j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'templates'))) - breakpoint() - template = j2_env.get_template('report.html') # dest_dir = os.path.dirname(crispresso_report_file) # shutil.copy2(os.path.join(_ROOT,'templates','CRISPResso_justcup.png'),dest_dir) # shutil.copy2(os.path.join(_ROOT,'templates','favicon.ico'),dest_dir) - outfile = open(crispresso_report_file, 'w') - outfile.write(template.render(report_data=report_data)) - outfile.close() + with open(crispresso_report_file, 'w') as outfile: + outfile.write(render_template( + 'report.html', j2_env, report_data=report_data, + )) def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info, batch_folder, _ROOT): @@ -478,13 +477,13 @@ def fill_default(dictionary, key, default_type=list): ) j2_env.filters['dirname'] = dirname if crispresso_tool == 'batch': - template = j2_env.get_template('batchReport.html') + template = 'batchReport.html' elif crispresso_tool == 'pooled': - template = j2_env.get_template('pooledReport.html') + template = 'pooledReport.html' elif crispresso_tool == 'wgs': - template = j2_env.get_template('wgsReport.html') + template = 'wgsReport.html' else: - template = j2_env.get_template('multiReport.html') + template = 'multiReport.html' crispresso_data_path = os.path.relpath( crispresso_folder, os.path.dirname(crispresso_multi_report_file), @@ -516,7 +515,9 @@ def fill_default(dictionary, key, default_type=list): for html in sub_html_files: sub_html_files[html] = crispresso_data_path + sub_html_files[html] with open(crispresso_multi_report_file, 'w') as outfile: - outfile.write(template.render( + outfile.write(render_template( + template, + j2_env, window_nuc_pct_quilts=window_nuc_pct_quilts, nuc_pct_quilts=nuc_pct_quilts, window_nuc_conv_plots=window_nuc_conv_plots, From c3781e9c71e20f8b11bfa51d709df1f50bb95e6b Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Thu, 30 Jun 2022 00:05:40 -0600 Subject: [PATCH 05/33] Update path to template directory to include `CRISPRessoReports` --- CRISPRessoReport.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py index 1cc809b2..83d94ed6 100644 --- a/CRISPRessoReport.py +++ b/CRISPRessoReport.py @@ -162,7 +162,7 @@ def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, web_ 'crispresso_data_path': crispresso_data_path, } - j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'templates'))) + j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates'))) # dest_dir = os.path.dirname(crispresso_report_file) # shutil.copy2(os.path.join(_ROOT,'templates','CRISPResso_justcup.png'),dest_dir) @@ -473,7 +473,7 @@ def fill_default(dictionary, key, default_type=list): dictionary[key] = default_type() j2_env = Environment( - loader=FileSystemLoader(os.path.join(_ROOT, 'templates')), + loader=FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates')), ) j2_env.filters['dirname'] = dirname if crispresso_tool == 'batch': From 1061ebb3de0f0c0a4773213f5f0b5aa97f28fc79 Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Thu, 30 Jun 2022 00:25:14 -0600 Subject: [PATCH 06/33] Update indentation in report.html and extract log params into partial --- templates/report.html | 72 ++++++++++------------- templates/shared/partials/log_params.html | 11 ++++ 2 files changed, 42 insertions(+), 41 deletions(-) create mode 100644 templates/shared/partials/log_params.html diff --git a/templates/report.html b/templates/report.html index 50e0868b..b3ef054f 100644 --- a/templates/report.html +++ b/templates/report.html @@ -54,47 +54,37 @@
-
-
- -
-
- {% if report_data['report_display_name'] != '' %} -
{{report_data['report_display_name']}}
- {% endif %} -
CRISPResso2 run information
- -
-
-
-
- {{report_data['figures']['htmls']['plot_1a']|safe}} - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_1a'] %} -

Data: {{data_label}}

- {% endfor %} -
-
-

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

-

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

-

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

- {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} -

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

- {% endif %} -

Command used:

{{report_data['run_data']['running_info']['command_used']}}

-

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

-

Running log

-
-
-
-
+
+
+ +
+
+ {% if report_data['report_display_name'] != '' %} +
{{report_data['report_display_name']}}
+ {% endif %} +
CRISPResso2 run information
+ +
+
+
+
+ {{report_data['figures']['htmls']['plot_1a']|safe}} + + {% for (data_label,data_path) in report_data['figures']['datas']['plot_1a'] %} +

Data: {{data_label}}

+ {% endfor %} +
+ {{ render_partial('shared/partials/log_params.html', report_data=report_data) }} +
+
+
diff --git a/templates/shared/partials/log_params.html b/templates/shared/partials/log_params.html new file mode 100644 index 00000000..ad035ae3 --- /dev/null +++ b/templates/shared/partials/log_params.html @@ -0,0 +1,11 @@ +
+

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

+

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

+

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

+ {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} +

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

+ {% endif %} +

Command used:

{{report_data['run_data']['running_info']['command_used']}}

+

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

+

Running log

+
From 073f1fe5c55941cc5a759c63782783bbbfb2a5a8 Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Wed, 6 Jul 2022 15:02:30 -0600 Subject: [PATCH 07/33] Added a few changes from the selenium-tests branch on C2Web --- templates/batchReport.html | 4 ++-- templates/pooledReport.html | 2 +- templates/report.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/batchReport.html b/templates/batchReport.html index 10b4e4e2..030d0450 100644 --- a/templates/batchReport.html +++ b/templates/batchReport.html @@ -54,12 +54,12 @@ {% if run_names|length > 0 %}
-
{{report_name}}
+
{{report_name}}
{% for run_name in run_names %} - {{run_name}} + {{run_name}} {% endfor %}
diff --git a/templates/pooledReport.html b/templates/pooledReport.html index 9ae88cc6..aa31ba15 100644 --- a/templates/pooledReport.html +++ b/templates/pooledReport.html @@ -70,7 +70,7 @@
{{report_name}}
{% for plot_name in summary_plot_names %}
-
{{summary_plot_titles[plot_name]}}
+
{{summary_plot_titles[plot_name]}}
diff --git a/templates/report.html b/templates/report.html index b3ef054f..b85fe2ea 100644 --- a/templates/report.html +++ b/templates/report.html @@ -402,7 +402,7 @@
Indel characterization
{% else %}
Indel characterization for {{amplicon_name}}
{% endif %} -
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partials('shared/partials/fig_summaries.html', plot_name=plot_name, summary_plot_htmls=summary_plot_htmls, crispresso_data_path=crispresso_data_path, summary_plot_labels=summary_plot_labels, summary_plot_datas=summary_plot_datas) }}
{% endfor %} diff --git a/templates/report.html b/templates/report.html index b85fe2ea..84c849e9 100644 --- a/templates/report.html +++ b/templates/report.html @@ -75,11 +75,7 @@
CRISPResso2 run information
- {{report_data['figures']['htmls']['plot_1a']|safe}} - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_1a'] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1a')}}
{{ render_partial('shared/partials/log_params.html', report_data=report_data) }}
@@ -105,156 +101,116 @@
Allele assignments
-
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_1b'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1b')}}
-
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_1c'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1c')}}
{% if report_data['figures']['locs']['plot_1d'] %}
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_1d'] %} -

Data: {{data_label}}

- {% endfor %} -
- {% endif %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1d')}} +
+ {% endif %}
{# end card #} {# start global coding sequence report #} - {% if report_data['figures']['locs']['plot_5a'] %} -
-
-
Global frameshift analysis
-
-
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_5a'] %} -

Data: {{data_label}}

- {% endfor %} -
-
- {% endif %} + {% if report_data['figures']['locs']['plot_5a'] %} +
+
+
Global frameshift analysis
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5a')}} +
+
+ {% endif %} - {% if report_data['figures']['locs']['plot_6a'] %} -
-
-
Global frameshift mutagenesis profiles
-
-
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_6a'] %} -

Data: {{data_label}}

- {% endfor %} -
-
- {% endif %} + {% if report_data['figures']['locs']['plot_6a'] %} +
+
+
Global frameshift mutagenesis profiles
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6a')}} +
+
+ {% endif %} - {% if report_data['figures']['locs']['plot_8a'] %} -
-
-
Global splicing analysis
-
-
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_8a'] %} -

Data: {{data_label}}

- {% endfor %} -
-
- {% endif %} - {# end of global coding sequence analysis #} + {% if report_data['figures']['locs']['plot_8a'] %} +
+
+
Global splicing analysis
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a')}} +
+
+ {% endif %} + {# end of global coding sequence analysis #} {# start hdr summary #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
HDR summary plot
- {% else %} -
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- - - {% for (data_label,data_path) in report_data['figures']['datas'][report_data.amplicons[0]]['plot_4g'] %} -

Data: {{data_label}}

- {% endfor %} -
-
+ {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
HDR summary plot
+ {% else %} +
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
{% endif %} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', amplicon_name=report_data.amplicons[0])}} +
+
+ {% endif %} {# end HDR summary #} {# start prime editing report #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} -
-
+ {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} +
+
{% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing report
+
Prime editing report
{% else %} -
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
+
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
{% endif %} -
-
- - - {% for (data_label,data_path) in report_data['figures']['datas'][report_data.amplicons[0]]['plot_11a'] %} -

Data: {{data_label}}

- {% endfor %} -
- {% endif %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', amplicon_name=report_data.amplicons[0])}} +
+
+ {% endif %} {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} -
-
+
+
{% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing summary plots at analysis positions
+
Prime editing summary plots at analysis positions
{% else %} -
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
+
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
{% endif %} -
-
- {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][report_data.amplicons[0]][fig_name] %} -

Data: {{data_label}}

- {% endfor %} -
+
+
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=report_data.amplicons[0])}} +
{% endfor %}
{% endif %} {# end plot 11b for prime editing #} - {% if report_data['figures']['locs']['plot_11c'] %} -
-
-
Scaffold insertions
-
-
- - - {% for (data_label,data_path) in report_data['figures']['datas']['plot_11c'] %} -

Data: {{data_label}}

- {% endfor %} + {% if report_data['figures']['locs']['plot_11c'] %} +
+
+
Scaffold insertions
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c')}}
{% endif %} @@ -339,11 +295,7 @@
Nucleotide composition for {{amplicon_name}}
{% if report_data['figures']['sgRNA_based_names'][amplicon_name] and report_data['figures']['sgRNA_based_names'][amplicon_name]['2b']%}
{% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['2b'] %} - - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} {% endfor %}
{% endif %} @@ -374,22 +326,14 @@
Modification lengths for {{amplicon_name}}
{% if report_data['figures']['locs'][amplicon_name]['plot_3a'] %}
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_3a'] %} -

Data: {{data_label}}

- {% endfor %} -
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_3a', amplicon_name=amplicon_name)}} +
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_3b'] %}
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_3b'] %} -

Data: {{data_label}}

- {% endfor %} -
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_3b', amplicon_name=amplicon_name)}} +
{% endif %}
{# end card_body #} @@ -438,61 +382,36 @@
Indel characterization for {{amplicon_name}}
{% if report_data['figures']['locs'][amplicon_name]['plot_4a'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_4a'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4a', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4b'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_4b'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4b', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4c'] %} -
- - - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_4c'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4c', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4d'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_4d'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4d', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4e'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_4e'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4e', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4f'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_4f'] %} -

Data: {{data_label}}

- {% endfor %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4f', amplicon_name=amplicon_name)}}
{% endif %}
@@ -510,11 +429,7 @@
Frameshift analysis for {{amplicon_name}}
{% endif %}
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_5'] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5', amplicon_name=amplicon_name)}}
{% endif %} @@ -529,11 +444,7 @@
Frameshift mutagenesis profiles for {{amplicon_name}}
{% endif %}
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_6'] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6', amplicon_name=amplicon_name)}}
{% endif %} @@ -548,11 +459,7 @@
Coding mutations for {{amplicon_name}}
{% endif %}
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_7'] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_7', amplicon_name=amplicon_name)}}
{% endif %} @@ -567,11 +474,7 @@
Splicing for {{amplicon_name}}
{% endif %}
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_8'] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8', amplicon_name=amplicon_name)}}
{% endif %} @@ -588,13 +491,9 @@
Allele plots for {{amplicon_name}}
{% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['9'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} -
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} +
{% endfor %}
@@ -630,96 +529,61 @@
Base editing for {{amplicon_name}}
{% endif %} -
-
-
+
+
+
{% if report_data['figures']['locs'][amplicon_name]['plot_10c'] %} -
-
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_10a'] %} -

Data: {{data_label}}

- {% endfor %} -
-
- - +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10a', amplicon_name=amplicon_name)}} +
+
- {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_10b'] %} -

Data: {{data_label}}

- {% endfor %} - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_10c'] %} -

Data: {{data_label}}

- {% endfor %} -
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10b', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10c', amplicon_name=amplicon_name)}}
+
{% else %} -
-
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_10a'] %} -

Data: {{data_label}}

- {% endfor %} -
-
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name]['plot_10b'] %} -

Data: {{data_label}}

- {% endfor %} -
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10a', amplicon_name=amplicon_name)}} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10b', amplicon_name=amplicon_name)}} +
{% endif %} {% if report_data['figures']['sgRNA_based_names'][amplicon_name] and report_data['figures']['sgRNA_based_names'][amplicon_name]['10d']%} -
- {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10d'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} -
- {% endfor %} -
+
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10d'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} +
+ {% endfor %} +
{% endif %} {% if report_data['figures']['sgRNA_based_names'][amplicon_name] and report_data['figures']['sgRNA_based_names'][amplicon_name]['10e']%} -
- {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10e'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} -
- {% endfor %} -
+
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10e'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} +
+ {% endfor %} +
{% endif %} {% if report_data['figures']['sgRNA_based_names'][amplicon_name] and report_data['figures']['sgRNA_based_names'][amplicon_name]['10f']%} -
- {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10f'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} -
- {% endfor %} - - {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10g'] %} -
- - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} -
- {% endfor %} +
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10f'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10f', amplicon_name=amplicon_name)}} +
+ {% endfor %} + {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10g'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10g', amplicon_name=amplicon_name)}} +
+ {% endfor %}
{% endif %} diff --git a/templates/shared/partials/fig_reports.html b/templates/shared/partials/fig_reports.html new file mode 100644 index 00000000..4ee65aa2 --- /dev/null +++ b/templates/shared/partials/fig_reports.html @@ -0,0 +1,23 @@ +
+ {% if amplicon_name %} + {% if report_data['figures']['htmls'][amplicon_name][fig_name] %} + {{report_data['figures']['htmls'][amplicon_name][fig_name]|safe}} + {% else %} + + {% endif %} + + {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% else %} + {% if report_data['figures']['htmls'][fig_name] %} + {{report_data['figures']['htmls'][fig_name]|safe}} + {% else %} + + {% endif %} + + {% for (data_label,data_path) in report_data['figures']['datas'][fig_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endif %} +
\ No newline at end of file diff --git a/templates/shared/partials/fig_summaries.html b/templates/shared/partials/fig_summaries.html new file mode 100644 index 00000000..404e8a26 --- /dev/null +++ b/templates/shared/partials/fig_summaries.html @@ -0,0 +1,11 @@ +
+ {% if summary_plot_htmls[plot_name] %} + {{summary_plot_htmls[plot_name]|safe}} + {% else %} + + {% endif %} + + {% for (data_label,data_path) in summary_plot_datas[plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
\ No newline at end of file From 546397a73d59288205b1a5772cf83a8f513b7e5b Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Thu, 7 Jul 2022 10:11:15 -0400 Subject: [PATCH 09/33] summaries partials and html updates --- CRISPRessoReport.py | 11 +++-- templates/batchReport.html | 46 +++++------------ templates/multiReport.html | 52 ++++++-------------- templates/pooledReport.html | 10 ++-- templates/shared/partials/fig_summaries.html | 12 ++--- templates/wgsReport.html | 14 ++---- 6 files changed, 52 insertions(+), 93 deletions(-) diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py index 2880d7f4..305e0fe6 100644 --- a/CRISPRessoReport.py +++ b/CRISPRessoReport.py @@ -524,10 +524,13 @@ def fill_default(dictionary, key, default_type=list): window_nuc_conv_plots=window_nuc_conv_plots, nuc_conv_plots=nuc_conv_plots, crispresso_data_path=crispresso_data_path, - summary_plot_names=summary_plots['names'], - summary_plot_titles=summary_plots['titles'], - summary_plot_labels=summary_plots['labels'], - summary_plot_datas=summary_plots['datas'], + report_data={ + 'names': summary_plots['names'], + 'titles': summary_plots['titles'], + 'labels': summary_plots['labels'], + 'datas': summary_plots['datas'], + 'crispresso_data_path': crispresso_data_path, + }, run_names=run_names, sub_html_files=sub_html_files, report_name=report_name, diff --git a/templates/batchReport.html b/templates/batchReport.html index 030d0450..93a6996b 100644 --- a/templates/batchReport.html +++ b/templates/batchReport.html @@ -73,12 +73,8 @@
Nucleotide percentages around guides
{% for plot_name in window_nuc_pct_quilts %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -91,12 +87,8 @@
Nucleotide percentages in the entire amplicon
{% for plot_name in nuc_pct_quilts %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -109,12 +101,8 @@
Conversion of target bases around guides
{% for plot_name in window_nuc_conv_plots %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -127,29 +115,21 @@
Conversion of target bases in the entire amplicon
{% for plot_name in nuc_conv_plots %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
{% endif %} - {% if summary_plot_names|length > 0 %} - {% for plot_name in summary_plot_names %} + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %}
-
{{summary_plot_titles[plot_name]}}
+
{{report_data['titles'][plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} @@ -168,7 +148,7 @@
{{summary_plot_titles[plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#}
{# jumbotron_content #}
{# jumbrotron #} diff --git a/templates/multiReport.html b/templates/multiReport.html index 4f346efe..7cd6dd5b 100644 --- a/templates/multiReport.html +++ b/templates/multiReport.html @@ -58,7 +58,7 @@
{{report_name}}
{% for run_name in run_names %} - {{run_name}} + {{run_name}} {% endfor %}
@@ -72,12 +72,8 @@
Nucleotide percentages around guides
{% for plot_name in window_nuc_pct_quilts %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -90,12 +86,8 @@
Nucleotide percentages in the entire amplicon
{% for plot_name in nuc_pct_quilts %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -108,12 +100,8 @@
Conversion of target bases around guides
{% for plot_name in window_nuc_conv_plots %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -126,29 +114,21 @@
Conversion of target bases in the entire amplicon
{% for plot_name in nuc_conv_plots %} -
{{summary_plot_titles[plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
{% endif %} - {% if summary_plot_names|length > 0 %} - {% for plot_name in summary_plot_names %} + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %}
-
{{summary_plot_titles[plot_name]}}
+
{{report_data['titles'][plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} @@ -176,14 +156,14 @@
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
{{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} -

Data: {{data_label}}

+

Data: {{data_label}}

{% endfor %}
{{allele_modification_line_plot_htmls[line_plot_name]}} {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} -

Data: {{data_label}}

+

Data: {{data_label}}

{% endfor %}
@@ -261,7 +241,7 @@
Summary Plots
{% for compact_plot in compact_plots_to_show %} - + {% endfor %}
diff --git a/templates/pooledReport.html b/templates/pooledReport.html index bf29ed9b..93b2ed0b 100644 --- a/templates/pooledReport.html +++ b/templates/pooledReport.html @@ -66,14 +66,14 @@
{{report_name}}
{% endif %} - {% if summary_plot_names|length > 0 %} - {% for plot_name in summary_plot_names %} + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %}
-
{{summary_plot_titles[plot_name]}}
+
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', plot_name=plot_name, summary_plot_htmls=summary_plot_htmls, crispresso_data_path=crispresso_data_path, summary_plot_labels=summary_plot_labels, summary_plot_datas=summary_plot_datas) }} + {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} @@ -86,7 +86,7 @@
{{summary_plot_titles[plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#} {# jumbotron_content #} {# jumbrotron #} diff --git a/templates/shared/partials/fig_summaries.html b/templates/shared/partials/fig_summaries.html index 404e8a26..384b7d8a 100644 --- a/templates/shared/partials/fig_summaries.html +++ b/templates/shared/partials/fig_summaries.html @@ -1,11 +1,11 @@
- {% if summary_plot_htmls[plot_name] %} - {{summary_plot_htmls[plot_name]|safe}} + {% if report_data['htmls'][plot_name] %} + {{report_data['htmls'][plot_name]|safe}} {% else %} - + {% endif %} - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

+ + {% for (data_label,data_path) in report_data['datas'][plot_name] %} +

Data: {{data_label}}

{% endfor %}
\ No newline at end of file diff --git a/templates/wgsReport.html b/templates/wgsReport.html index 3cf2c781..74b0447c 100644 --- a/templates/wgsReport.html +++ b/templates/wgsReport.html @@ -64,18 +64,14 @@
{{report_name}}
- {% if summary_plot_names|length > 0 %} - {% for plot_name in summary_plot_names %} + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %}
-
{{summary_plot_titles[plot_name]}}
+
{{report_data['titles'][plot_name]}}
- - - {% for (data_label,data_path) in summary_plot_datas[plot_name] %} -

Data: {{data_label}}

- {% endfor %} + {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} @@ -88,7 +84,7 @@
{{summary_plot_titles[plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#} {# jumbotron_content #} {# jumbrotron #} From 290d829f3b20f4186694a3895bb31200ef4a6d8f Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Thu, 7 Jul 2022 09:11:02 -0600 Subject: [PATCH 10/33] Fix error when rendering multi reports --- templates/batchReport.html | 10 +++++----- templates/multiReport.html | 10 +++++----- templates/pooledReport.html | 2 +- templates/wgsReport.html | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/templates/batchReport.html b/templates/batchReport.html index 93a6996b..d02c6269 100644 --- a/templates/batchReport.html +++ b/templates/batchReport.html @@ -74,7 +74,7 @@
Nucleotide percentages around guides
{% for plot_name in window_nuc_pct_quilts %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -88,7 +88,7 @@
Nucleotide percentages in the entire amplicon
{% for plot_name in nuc_pct_quilts %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -102,7 +102,7 @@
Conversion of target bases around guides
{% for plot_name in window_nuc_conv_plots %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -116,7 +116,7 @@
Conversion of target bases in the entire amplicon
{% for plot_name in nuc_conv_plots %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -129,7 +129,7 @@
{{report_data['titles'][plot_name]}}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} diff --git a/templates/multiReport.html b/templates/multiReport.html index 7cd6dd5b..8e8d83ca 100644 --- a/templates/multiReport.html +++ b/templates/multiReport.html @@ -73,7 +73,7 @@
Nucleotide percentages around guides
{% for plot_name in window_nuc_pct_quilts %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -87,7 +87,7 @@
Nucleotide percentages in the entire amplicon
{% for plot_name in nuc_pct_quilts %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -101,7 +101,7 @@
Conversion of target bases around guides
{% for plot_name in window_nuc_conv_plots %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -115,7 +115,7 @@
Conversion of target bases in the entire amplicon
{% for plot_name in nuc_conv_plots %}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} {% endfor %}
@@ -128,7 +128,7 @@
{{report_data['titles'][plot_name]}}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} diff --git a/templates/pooledReport.html b/templates/pooledReport.html index 93b2ed0b..5128785a 100644 --- a/templates/pooledReport.html +++ b/templates/pooledReport.html @@ -73,7 +73,7 @@
{{report_name}}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} diff --git a/templates/wgsReport.html b/templates/wgsReport.html index 74b0447c..0a5a1277 100644 --- a/templates/wgsReport.html +++ b/templates/wgsReport.html @@ -71,7 +71,7 @@
{{report_name}}
{{report_data['titles'][plot_name]}}
- {{ render_partials('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }}
{% endfor %} From 8f5d8a1136cbe16c5daf78da24655374e01b4f5d Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Mon, 22 Aug 2022 10:21:10 -0600 Subject: [PATCH 11/33] Layout.html for C2WEB and CLI --- templates/layout.html | 93 +++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/templates/layout.html b/templates/layout.html index 05a1e959..0efa21f7 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -7,7 +7,8 @@ - + + @@ -22,12 +23,14 @@ - + - -{% endblock %} - -{% block content %} -
-
-
- -
-
- - {% if run_names|length > 0 %} -
-
-
{{report_name}}
-
-
-
- {% for run_name in run_names %} - {{run_name}} - {% endfor %} -
-
-
- {% endif %} - - {% if window_nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages around guides
-
-
- {% for plot_name in window_nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages in the entire amplicon
-
-
- {% for plot_name in nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if window_nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases around guides
-
-
- {% for plot_name in window_nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases in the entire amplicon
-
-
- {% for plot_name in nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - -
- -
- - - - {# data bit for web version: #} - {# -

Data: {{data_label}}

- #} -
{# jumbotron_content #} -
{# jumbrotron #} - - {# column #} - -
- -{% endblock %} - -{% block foot %} -{% endblock %} diff --git a/templates/favicon.ico b/templates/favicon.ico deleted file mode 100644 index 8aed2d0743b52f12c1f0f8b2b4c439ba77091af3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmbVMTWeE65MIGIUy2Vt`{*xIQTtGpYE@zjwT6~P+tO3xNz+rB6BBFO#3;0l0Sg5a zZAl=|kQxgi_XiV_ko)E9&Xx@^1Pab!cV@nwZ)Rt5au~b9pOF#9_nYkQRmN^G#%}S& zA&y+&TrtMau3x)Y!si1jMS7+{#1gs$u8 zbUGr3j2X-&@p8G0S4Jb0RSQPWS&7j;UxRtyjV~aI9)ri>NaQ} z>~Oeuu(+b&=h3fA`*^3SaBOd3!|A}9U5943;giRWWz~!c!wYD(4dnBAQA^%g>LQ<) zs%h}-?+MOFw+owmecsy@dCWZbuGb5@(>av?=j;rMMTMfi$Kz)c7#knQqo+?`G?`%A zbYkx98F-lC8jXMI_VcApG3|C6>2zAuA-}}uB7YyLWxUk& zdL5Ze2Dw~LK*?khg+c+OoBUm*vs5Z2Y{?-l?@je8m5Ml`8pI$zXSiP&jEy - - - CRISPResso2 - - - - - - - - - - - - - - - - - - - - - - - {% if current_user is defined %} - - {% else %} - - {% endif %} - - - - - {% block head %}{% endblock %} - - - - - {% if current_user is defined %} -
- {{ self.help_block() }} -
- - {% with messages = get_flashed_messages(with_categories=true) %} - {% if messages %} - {% for category, message in messages %} - {% if category == "error" %} - - {% else %} - - {% endif %} - {% endfor %} - {% endif %} - {% endwith %} - {% endif %} - - {# if default user (normal crispresso mode) #} - {% if current_user == null or not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} - -
-
-
- {% if current_user is defined %} -
- {% else %} -
- {% endif %} -
-
-

CRISPResso2

-

Analysis of genome editing outcomes from deep sequencing data

-
-
-
-
- - - {% else %} - {# if doing user sessions #} - -
- {% endif %} - -
-
-
-
- {% block help_block %} {% endblock %} -
-
-
-
- - {% block content %}{% endblock %} - - {% if current_user is defined and (not current_user.is_anonymous and current_user.username == "DEFAULTUSER") %} -
-
- -
-
- {% else %} -
-
- -
-
- {% endif %} - - - - - - - {% block foot %}{% endblock %} - - - diff --git a/templates/multiReport.html b/templates/multiReport.html deleted file mode 100644 index b6784e4a..00000000 --- a/templates/multiReport.html +++ /dev/null @@ -1,265 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
- -
-
- - {% if run_names|length > 0 %} - - {% endif %} - - {% if window_nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages around guides
-
-
- {% for plot_name in window_nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages in the entire amplicon
-
-
- {% for plot_name in nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if window_nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases around guides
-
-
- {% for plot_name in window_nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases in the entire amplicon
-
-
- {% for plot_name in nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - {% if allele_modification_heatmap_plot_names|length > 0 %} - {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} - {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} - {% set modification_type = heatmap_plot_name.split('_')[3] %} -
-
-
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
- -
-
-
-
- {{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} - - {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
-
- {{allele_modification_line_plot_htmls[line_plot_name]}} - - {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
-
-
-
- - {% endfor %} - - - - {% endif %} - - {% if compact_plots_to_show|length > 0 %} -
-
-
Summary Plots
-
-
-
- {% for compact_plot in compact_plots_to_show %} - - {% endfor %} -
-
-
- {% endif %} - - -
- -
- -
{# jumbotron_content #} -
{# jumbrotron #} - -
{# column #} - -
-{% endblock %} - -{% block foot %} -{% endblock %} diff --git a/templates/pooledReport.html b/templates/pooledReport.html deleted file mode 100644 index ceb40426..00000000 --- a/templates/pooledReport.html +++ /dev/null @@ -1,101 +0,0 @@ -{% extends "CRISPRessoReports/templates/layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
- -
-
- - {% if run_names|length > 0 %} -
-
-
{{report_name}}
-
-
-
- {% for region_name in run_names %} - {{region_name}} - {% endfor %} -
-
-
- {% endif %} - - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - - {# data bit for web version: #} - {# -

Data: {{data_label}}

- #} -
{# jumbotron_content #} -
{# jumbrotron #} - -
{# column #} - -
-
-{% endblock %} - -{% block foot %} -{% endblock %} diff --git a/templates/report.html b/templates/report.html deleted file mode 100644 index 882d6731..00000000 --- a/templates/report.html +++ /dev/null @@ -1,698 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
-
-
-
- {% if report_data['report_display_name'] != '' %} -
{{report_data['report_display_name']}}
- {% endif %} -
CRISPResso2 run information
- -
-
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1a')}} -
- {{ render_partial('CRISPRessoReports/templates/shared/partials/log_params.html', report_data=report_data) }} -
-
-
- -
-
-
Allele assignments
- -
-
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1b')}} -
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1c')}} -
- {% if report_data['figures']['locs']['plot_1d'] %} -
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1d')}} -
- {% endif %} -
-
-
{# end card #} - - {# start global coding sequence report #} - {% if report_data['figures']['locs']['plot_5a'] %} -
-
-
Global frameshift analysis
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5a')}} -
-
- {% endif %} - - {% if report_data['figures']['locs']['plot_6a'] %} -
-
-
Global frameshift mutagenesis profiles
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6a')}} -
-
- {% endif %} - - {% if report_data['figures']['locs']['plot_8a'] %} -
-
-
Global splicing analysis
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a')}} -
-
- {% endif %} - {# end of global coding sequence analysis #} - - {# start hdr summary #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
HDR summary plot
- {% else %} -
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', amplicon_name=report_data.amplicons[0])}} -
-
- {% endif %} - {# end HDR summary #} - - {# start prime editing report #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing report
- {% else %} -
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', amplicon_name=report_data.amplicons[0])}} -
-
- {% endif %} - - {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing summary plots at analysis positions
- {% else %} -
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} -
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=report_data.amplicons[0])}} -
- {% endfor %} -
-
- {% endif %} - {# end plot 11b for prime editing #} - - {% if report_data['figures']['locs']['plot_11c'] %} -
-
-
Scaffold insertions
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c')}} -
-
- {% endif %} - {# end prime editing section #} - - {% if report_data.amplicons|length == 1 %} -
{# if only one amplicon, just a normal div #} - {% else %} - {# If there is more than one amplicon, print a navigation to show each amplicon #} -

Reads are aligned to each amplicon sequence separately. Quantification and visualization of these reads are shown for each amplicon below:

-
-
-
Amplicons
- -
- {% endif %} {# end if report contains more than one amplicon #} - - - {% if report_data.amplicons|length == 1 %} {# if only one amplicon, just a normal div #} -
- {% else %} - {# tab content #} -
-
{# jumbotron_content #} -
{# jumbrotron #} -
{# column #} -
- -
-{% endblock %} - -{% block foot %} - -{% endblock %} diff --git a/templates/shared/partials/fig_reports.html b/templates/shared/partials/fig_reports.html deleted file mode 100644 index 6f7e448e..00000000 --- a/templates/shared/partials/fig_reports.html +++ /dev/null @@ -1,31 +0,0 @@ -
- {% if amplicon_name is defined %} - {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'][amplicon_name] %} - {{report_data['figures']['htmls'][amplicon_name][fig_name]|safe}} - {% else %} - {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} - - {% else %} - - {% endif %} - {% endif %} - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} - {% else %} - {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'] %} - {{report_data['figures']['htmls'][fig_name]|safe}} - {% else %} - {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} - - {% else %} - - {% endif %} - {% endif %} - - {% for (data_label,data_path) in report_data['figures']['datas'][fig_name] %} -

Data: {{data_label}}

- {% endfor %} - {% endif %} -
\ No newline at end of file diff --git a/templates/shared/partials/fig_summaries.html b/templates/shared/partials/fig_summaries.html deleted file mode 100644 index 384b7d8a..00000000 --- a/templates/shared/partials/fig_summaries.html +++ /dev/null @@ -1,11 +0,0 @@ -
- {% if report_data['htmls'][plot_name] %} - {{report_data['htmls'][plot_name]|safe}} - {% else %} - - {% endif %} - - {% for (data_label,data_path) in report_data['datas'][plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
\ No newline at end of file diff --git a/templates/shared/partials/log_params.html b/templates/shared/partials/log_params.html deleted file mode 100644 index ad035ae3..00000000 --- a/templates/shared/partials/log_params.html +++ /dev/null @@ -1,11 +0,0 @@ -
-

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

-

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

-

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

- {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} -

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

- {% endif %} -

Command used:

{{report_data['run_data']['running_info']['command_used']}}

-

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

-

Running log

-
diff --git a/templates/wgsReport.html b/templates/wgsReport.html deleted file mode 100644 index aba5afc6..00000000 --- a/templates/wgsReport.html +++ /dev/null @@ -1,99 +0,0 @@ -{% extends "CRISPRessoReports/templates/layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
- -
-
- -
-
-
{{report_name}}
-
-
-
- {% for region_name in run_names %} - {{region_name}} - {% endfor %} -
-
-
- - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('CRISPRessoReports/templates/shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - - {# data bit for web version: #} - {# -

Data: {{data_label}}

- #} -
{# jumbotron_content #} -
{# jumbrotron #} - -
{# column #} - -
-
-{% endblock %} - -{% block foot %} -{% endblock %} From 84174e6393ac68874698e910e1ba3d5daf098e3e Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Sat, 10 Sep 2022 13:02:11 -0600 Subject: [PATCH 16/33] Squashed 'CRISPRessoWEB/CRISPRessoReports/' content from commit 7d9b4e5 git-subtree-dir: CRISPRessoWEB/CRISPRessoReports git-subtree-split: 7d9b4e54795c7459c917da50797c0fc5e30f8de7 --- CRISPRessoReport.py | 18 +- templates/CRISPResso_justcup.png | Bin 0 -> 42782 bytes templates/batchReport.html | 163 +++++ templates/favicon.ico | Bin 0 -> 1150 bytes templates/layout.html | 237 +++++++ templates/multiReport.html | 265 +++++++ templates/pooledReport.html | 101 +++ templates/report.html | 693 +++++++++++++++++++ templates/shared/partials/fig_reports.html | 31 + templates/shared/partials/fig_summaries.html | 11 + templates/shared/partials/log_params.html | 11 + templates/wgsReport.html | 99 +++ 12 files changed, 1617 insertions(+), 12 deletions(-) create mode 100644 templates/CRISPResso_justcup.png create mode 100644 templates/batchReport.html create mode 100644 templates/favicon.ico create mode 100644 templates/layout.html create mode 100644 templates/multiReport.html create mode 100644 templates/pooledReport.html create mode 100644 templates/report.html create mode 100644 templates/shared/partials/fig_reports.html create mode 100644 templates/shared/partials/fig_summaries.html create mode 100644 templates/shared/partials/log_params.html create mode 100644 templates/wgsReport.html diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py index 79a4cd1e..58cf42ac 100644 --- a/CRISPRessoReport.py +++ b/CRISPRessoReport.py @@ -5,7 +5,7 @@ ''' import os -from jinja2 import Environment, FileSystemLoader, ChoiceLoader +from jinja2 import Environment, FileSystemLoader from jinja_partials import generate_render_partial, render_partial from CRISPResso2 import CRISPRessoShared @@ -163,11 +163,7 @@ def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, web_ 'crispresso_data_path': crispresso_data_path, } - loader1 = FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates')) - loader2 = FileSystemLoader(os.path.join(_ROOT, 'templates')) - loader = ChoiceLoader([loader1, loader2]) - - j2_env = Environment(loader=loader) + j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates'))) # dest_dir = os.path.dirname(crispresso_report_file) # shutil.copy2(os.path.join(_ROOT,'templates','CRISPResso_justcup.png'),dest_dir) @@ -477,12 +473,9 @@ def fill_default(dictionary, key, default_type=list): if key not in dictionary: dictionary[key] = default_type() - loader1 = FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates')) - loader2 = FileSystemLoader(os.path.join(_ROOT, 'templates')) - loader = ChoiceLoader([loader1, loader2]) - - j2_env = Environment(loader=loader) - + j2_env = Environment( + loader=FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates')), + ) j2_env.filters['dirname'] = dirname if crispresso_tool == 'batch': template = 'batchReport.html' @@ -536,6 +529,7 @@ def fill_default(dictionary, key, default_type=list): 'titles': summary_plots['titles'], 'labels': summary_plots['labels'], 'datas': summary_plots['datas'], + 'htmls': [], 'crispresso_data_path': crispresso_data_path, }, run_names=run_names, diff --git a/templates/CRISPResso_justcup.png b/templates/CRISPResso_justcup.png new file mode 100644 index 0000000000000000000000000000000000000000..3116c48c394f23cf37669c6dbb92928ef0d88b9d GIT binary patch literal 42782 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 literal 0 HcmV?d00001 diff --git a/templates/batchReport.html b/templates/batchReport.html new file mode 100644 index 00000000..d02c6269 --- /dev/null +++ b/templates/batchReport.html @@ -0,0 +1,163 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+ +
+
+ + {% if run_names|length > 0 %} +
+
+
{{report_name}}
+
+
+
+ {% for run_name in run_names %} + {{run_name}} + {% endfor %} +
+
+
+ {% endif %} + + {% if window_nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages around guides
+
+
+ {% for plot_name in window_nuc_pct_quilts %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages in the entire amplicon
+
+
+ {% for plot_name in nuc_pct_quilts %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if window_nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases around guides
+
+
+ {% for plot_name in window_nuc_conv_plots %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases in the entire amplicon
+
+
+ {% for plot_name in nuc_conv_plots %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %} +
+
+
{{report_data['titles'][plot_name]}}
+
+
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} +
+
+ {% endfor %} + {% endif %} + + +
+ +
+ + + + {# data bit for web version: #} + {# +

Data: {{data_label}}

+ #} +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+ +{% endblock %} + +{% block foot %} +{% endblock %} diff --git a/templates/favicon.ico b/templates/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8aed2d0743b52f12c1f0f8b2b4c439ba77091af3 GIT binary patch literal 1150 zcmbVMTWeE65MIGIUy2Vt`{*xIQTtGpYE@zjwT6~P+tO3xNz+rB6BBFO#3;0l0Sg5a zZAl=|kQxgi_XiV_ko)E9&Xx@^1Pab!cV@nwZ)Rt5au~b9pOF#9_nYkQRmN^G#%}S& zA&y+&TrtMau3x)Y!si1jMS7+{#1gs$u8 zbUGr3j2X-&@p8G0S4Jb0RSQPWS&7j;UxRtyjV~aI9)ri>NaQ} z>~Oeuu(+b&=h3fA`*^3SaBOd3!|A}9U5943;giRWWz~!c!wYD(4dnBAQA^%g>LQ<) zs%h}-?+MOFw+owmecsy@dCWZbuGb5@(>av?=j;rMMTMfi$Kz)c7#knQqo+?`G?`%A zbYkx98F-lC8jXMI_VcApG3|C6>2zAuA-}}uB7YyLWxUk& zdL5Ze2Dw~LK*?khg+c+OoBUm*vs5Z2Y{?-l?@je8m5Ml`8pI$zXSiP&jEy + + + CRISPResso2 + + + + + + + + + + + + + + + + + + + + + + + {% if current_user is defined %} + + {% else %} + + {% endif %} + + + + + {% block head %}{% endblock %} + + + + + {% if current_user is defined %} +
+ {{ self.help_block() }} +
+ + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} + {% if category == "error" %} + + {% else %} + + {% endif %} + {% endfor %} + {% endif %} + {% endwith %} + {% endif %} + + {# if default user (normal crispresso mode) #} + {% if current_user == null or not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} + +
+
+
+ {% if current_user is defined %} +
+ {% else %} +
+ {% endif %} +
+
+

CRISPResso2

+

Analysis of genome editing outcomes from deep sequencing data

+
+
+
+
+ + + {% else %} + {# if doing user sessions #} + +
+ {% endif %} + +
+
+
+
+ {% block help_block %} {% endblock %} +
+
+
+
+ + {% block content %}{% endblock %} + + {% if current_user is defined and (not current_user.is_anonymous and current_user.username == "DEFAULTUSER") %} +
+
+ +
+
+ {% else %} +
+
+ +
+
+ {% endif %} +
+ + + + + + + {% block foot %}{% endblock %} + + + diff --git a/templates/multiReport.html b/templates/multiReport.html new file mode 100644 index 00000000..8e8d83ca --- /dev/null +++ b/templates/multiReport.html @@ -0,0 +1,265 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+ +
+
+ + {% if run_names|length > 0 %} +
+
+
{{report_name}}
+
+
+
+ {% for run_name in run_names %} + {{run_name}} + {% endfor %} +
+
+
+ {% endif %} + + {% if window_nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages around guides
+
+
+ {% for plot_name in window_nuc_pct_quilts %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages in the entire amplicon
+
+
+ {% for plot_name in nuc_pct_quilts %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if window_nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases around guides
+
+
+ {% for plot_name in window_nuc_conv_plots %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases in the entire amplicon
+
+
+ {% for plot_name in nuc_conv_plots %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %} +
+
+
{{report_data['titles'][plot_name]}}
+
+
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} +
+
+ {% endfor %} + {% endif %} + + {% if allele_modification_heatmap_plot_names|length > 0 %} + {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} + {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} + {% set modification_type = heatmap_plot_name.split('_')[3] %} +
+
+
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
+ +
+
+
+
+ {{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} + + {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+ {{allele_modification_line_plot_htmls[line_plot_name]}} + + {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+
+
+ + {% endfor %} + + + + {% endif %} + + {% if compact_plots_to_show|length > 0 %} +
+
+
Summary Plots
+
+
+
+ {% for compact_plot in compact_plots_to_show %} + + {% endfor %} +
+
+
+ {% endif %} + + +
+ +
+ +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+{% endblock %} + +{% block foot %} +{% endblock %} diff --git a/templates/pooledReport.html b/templates/pooledReport.html new file mode 100644 index 00000000..f4550e82 --- /dev/null +++ b/templates/pooledReport.html @@ -0,0 +1,101 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+ +
+
+ + {% if run_names|length > 0 %} +
+
+
{{report_name}}
+
+
+
+ {% for region_name in run_names %} + {{region_name}} + {% endfor %} +
+
+
+ {% endif %} + + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %} +
+
+
{{report_data['titles'][plot_name]}}
+
+
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} +
+
+ {% endfor %} + {% endif %} + + + {# data bit for web version: #} + {# +

Data: {{data_label}}

+ #} +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+
+{% endblock %} + +{% block foot %} +{% endblock %} diff --git a/templates/report.html b/templates/report.html new file mode 100644 index 00000000..fb755d18 --- /dev/null +++ b/templates/report.html @@ -0,0 +1,693 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+
+
+
+ {% if report_data['report_display_name'] != '' %} +
{{report_data['report_display_name']}}
+ {% endif %} +
CRISPResso2 run information
+ +
+
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1a')}} +
+ {{ render_partial('shared/partials/log_params.html', report_data=report_data) }} +
+
+
+ +
+
+
Allele assignments
+ +
+
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1b')}} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1c')}} +
+ {% if report_data['figures']['locs']['plot_1d'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1d')}} +
+ {% endif %} +
+
+
{# end card #} + + {# start global coding sequence report #} + {% if report_data['figures']['locs']['plot_5a'] %} +
+
+
Global frameshift analysis
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5a')}} +
+
+ {% endif %} + + {% if report_data['figures']['locs']['plot_6a'] %} +
+
+
Global frameshift mutagenesis profiles
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6a')}} +
+
+ {% endif %} + + {% if report_data['figures']['locs']['plot_8a'] %} +
+
+
Global splicing analysis
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a')}} +
+
+ {% endif %} + {# end of global coding sequence analysis #} + + {# start hdr summary #} + {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
HDR summary plot
+ {% else %} +
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', amplicon_name=report_data.amplicons[0])}} +
+
+ {% endif %} + {# end HDR summary #} + + {# start prime editing report #} + {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
Prime editing report
+ {% else %} +
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', amplicon_name=report_data.amplicons[0])}} +
+
+ {% endif %} + + {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
Prime editing summary plots at analysis positions
+ {% else %} +
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=report_data.amplicons[0])}} +
+ {% endfor %} +
+
+ {% endif %} + {# end plot 11b for prime editing #} + + {% if report_data['figures']['locs']['plot_11c'] %} +
+
+
Scaffold insertions
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c')}} +
+
+ {% endif %} + {# end prime editing section #} + + {% if report_data.amplicons|length == 1 %} +
{# if only one amplicon, just a normal div #} + {% else %} + {# If there is more than one amplicon, print a navigation to show each amplicon #} +

Reads are aligned to each amplicon sequence separately. Quantification and visualization of these reads are shown for each amplicon below:

+
+
+
Amplicons
+ +
+ {% endif %} {# end if report contains more than one amplicon #} + + + {% if report_data.amplicons|length == 1 %} {# if only one amplicon, just a normal div #} +
+ {% else %} + {# jumbotron_content #} +
{# jumbrotron #} +
{# column #} +
+ +
+{% endblock %} + +{% block foot %} + +{% endblock %} diff --git a/templates/shared/partials/fig_reports.html b/templates/shared/partials/fig_reports.html new file mode 100644 index 00000000..6f7e448e --- /dev/null +++ b/templates/shared/partials/fig_reports.html @@ -0,0 +1,31 @@ +
+ {% if amplicon_name is defined %} + {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'][amplicon_name] %} + {{report_data['figures']['htmls'][amplicon_name][fig_name]|safe}} + {% else %} + {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} + + {% else %} + + {% endif %} + {% endif %} + + {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% else %} + {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'] %} + {{report_data['figures']['htmls'][fig_name]|safe}} + {% else %} + {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} + + {% else %} + + {% endif %} + {% endif %} + + {% for (data_label,data_path) in report_data['figures']['datas'][fig_name] %} +

Data: {{data_label}}

+ {% endfor %} + {% endif %} +
\ No newline at end of file diff --git a/templates/shared/partials/fig_summaries.html b/templates/shared/partials/fig_summaries.html new file mode 100644 index 00000000..e4e3297a --- /dev/null +++ b/templates/shared/partials/fig_summaries.html @@ -0,0 +1,11 @@ +
+ {% if report_data['htmls'][plot_name] %} + {{report_data['htmls'][plot_name]|safe}} + {% else %} + + {% endif %} + + {% for (data_label,data_path) in report_data['datas'][plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
diff --git a/templates/shared/partials/log_params.html b/templates/shared/partials/log_params.html new file mode 100644 index 00000000..ad035ae3 --- /dev/null +++ b/templates/shared/partials/log_params.html @@ -0,0 +1,11 @@ +
+

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

+

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

+

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

+ {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} +

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

+ {% endif %} +

Command used:

{{report_data['run_data']['running_info']['command_used']}}

+

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

+

Running log

+
diff --git a/templates/wgsReport.html b/templates/wgsReport.html new file mode 100644 index 00000000..0a5a1277 --- /dev/null +++ b/templates/wgsReport.html @@ -0,0 +1,99 @@ +{% extends "layout.html" %} +{% block head %} + + +{% endblock %} + +{% block content %} +
+
+
+ +
+
+ +
+
+
{{report_name}}
+
+
+
+ {% for region_name in run_names %} + {{region_name}} + {% endfor %} +
+
+
+ + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %} +
+
+
{{report_data['titles'][plot_name]}}
+
+
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} +
+
+ {% endfor %} + {% endif %} + + + {# data bit for web version: #} + {# +

Data: {{data_label}}

+ #} +
{# jumbotron_content #} +
{# jumbrotron #} + +
{# column #} + +
+
+{% endblock %} + +{% block foot %} +{% endblock %} From 321815d0c3599408afb6b1506f793275ff673f42 Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Tue, 13 Sep 2022 11:01:52 -0600 Subject: [PATCH 17/33] Removing CRISPRessoReport files --- CRISPRessoReport.py | 690 ------------------ templates/CRISPResso_justcup.png | Bin 42782 -> 0 bytes templates/batchReport.html | 163 ----- templates/favicon.ico | Bin 1150 -> 0 bytes templates/layout.html | 237 ------- templates/multiReport.html | 265 ------- templates/pooledReport.html | 101 --- templates/report.html | 693 ------------------- templates/shared/partials/fig_reports.html | 31 - templates/shared/partials/fig_summaries.html | 11 - templates/shared/partials/log_params.html | 11 - templates/wgsReport.html | 99 --- 12 files changed, 2301 deletions(-) delete mode 100644 CRISPRessoReport.py delete mode 100644 templates/CRISPResso_justcup.png delete mode 100644 templates/batchReport.html delete mode 100644 templates/favicon.ico delete mode 100644 templates/layout.html delete mode 100644 templates/multiReport.html delete mode 100644 templates/pooledReport.html delete mode 100644 templates/report.html delete mode 100644 templates/shared/partials/fig_reports.html delete mode 100644 templates/shared/partials/fig_summaries.html delete mode 100644 templates/shared/partials/log_params.html delete mode 100644 templates/wgsReport.html diff --git a/CRISPRessoReport.py b/CRISPRessoReport.py deleted file mode 100644 index 58cf42ac..00000000 --- a/CRISPRessoReport.py +++ /dev/null @@ -1,690 +0,0 @@ -''' -CRISPResso2 - Kendell Clement and Luca Pinello 2018 -Software pipeline for the analysis of genome editing outcomes from deep sequencing data -(c) 2020 The General Hospital Corporation. All Rights Reserved. -''' - -import os -from jinja2 import Environment, FileSystemLoader -from jinja_partials import generate_render_partial, render_partial -from CRISPResso2 import CRISPRessoShared - - -def render_template(template_name, jinja2_env, **data): - """Render a template with partials. - - Parameters - ---------- - template_name: str - The name of the template to render. For example, if you have a template - file called `templates/my_template.html` you would pass in - `my_template.html`. - jinja2_env: jinja2.Environment - The Jinja2 environment being used. - **data: keyword arguments of any type - Additional keyword arguments that are passed to the template. - - Returns - ------- - The rendered template. - """ - def custom_partial_render(partial_template_name, **partial_data): - template = jinja2_env.get_template(partial_template_name) - partial_data.update( - render_partial=generate_render_partial( - custom_partial_render, - ), - ) - return template.render(**partial_data) - return render_partial( - template_name, custom_partial_render, **data, - ) - - -def make_report_from_folder(crispresso_report_file, crispresso_folder, _ROOT): - """ - Makes an html report for a crispresso run - - Parameters: - crispresso_report_file (string): name of the html file to create - crispresso_folder (string): path to the crispresso output - _ROOT (string): path to crispresso executables (for templates) - - Returns: - Nothin - """ - run_data = CRISPRessoShared.load_crispresso_info(crispresso_folder) - make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT) - - -def add_fig_if_exists(fig_name, fig_root, fig_title, fig_caption, fig_data, - amplicon_fig_names, amplicon_figures, crispresso_folder): - """ - Helper function to add figure if the file exists - if fig at filename exists, - amplicon_figs[figname] is set to that file - """ - # fullpath=os.path.join(crispresso_folder,fig_root+'.png') - pngfullpath = os.path.join(crispresso_folder, fig_root + '.png') - htmlfullpath = os.path.join(crispresso_folder, fig_root + '.html') - # print('adding file ' + fig_root + ' at ' + fullpath) - if os.path.exists(pngfullpath) or os.path.exists(htmlfullpath): - amplicon_fig_names.append(fig_name) - # amplicon_fig_locs[fig_name]=os.path.basename(fig_root+'.png') - amplicon_figures['locs'][fig_name] = os.path.basename(fig_root) - amplicon_figures['titles'][fig_name] = fig_title - amplicon_figures['captions'][fig_name] = fig_caption - amplicon_figures['datas'][fig_name] = [] - for (data_caption, data_file) in fig_data: - if os.path.exists(os.path.join(crispresso_folder, data_file)): - amplicon_figures['datas'][fig_name].append((data_caption, data_file)) - if os.path.exists(htmlfullpath): - with open(htmlfullpath) as html: - html_string = "
" - html_string += html.read() - html_string += "
" - amplicon_figures['htmls'][fig_name] = html_string - - -def assemble_figs(run_data, crispresso_folder): - figures = {'names': {}, 'locs': {}, 'titles': {}, 'captions': {}, 'datas': {}, 'htmls': {}, 'sgRNA_based_names': {}} - - global_fig_names = [] - for fig in ['1a', '1b', '1c', '1d', '5a', '6a', '8a', '11c']: - fig_name = 'plot_' + fig - if fig_name + '_root' in run_data['results']['general_plots']: - add_fig_if_exists(fig_name, run_data['results']['general_plots'][fig_name + '_root'], 'Figure ' + fig, - run_data['results']['general_plots'][fig_name + '_caption'], - run_data['results']['general_plots'][fig_name + '_data'], - global_fig_names, figures, crispresso_folder) - - amplicons = [] - for amplicon_name in run_data['results']['ref_names']: - amplicons.append(amplicon_name) - amplicon_figures = {'names': [], 'locs': {}, 'titles': {}, 'captions': {}, 'datas': {}, 'htmls': {}} - - for fig in ['2a', '3a', '3b', '4a', '4b', '4c', '4d', '4e', '4f', '4g', '5', '6', '7', '8', '10a', '10b', '10c', - '11a']: - fig_name = 'plot_' + fig - if fig_name + '_root' in run_data['results']['refs'][amplicon_name]: - add_fig_if_exists(fig_name, run_data['results']['refs'][amplicon_name][fig_name + '_root'], - 'Figure ' + fig_name, - run_data['results']['refs'][amplicon_name][fig_name + '_caption'], - run_data['results']['refs'][amplicon_name][fig_name + '_data'], - global_fig_names, amplicon_figures, crispresso_folder) - - this_sgRNA_based_fig_names = {} - for fig in ['2b', '9', '10d', '10e', '10f', '10g', '11b']: - # fig 2b's - this_fig_names = [] - if 'plot_' + fig + '_roots' in run_data['results']['refs'][amplicon_name]: - for idx, plot_root in enumerate(run_data['results']['refs'][amplicon_name]['plot_' + fig + '_roots']): - fig_name = "plot_" + fig + "_" + str(idx) - add_fig_if_exists(fig_name, plot_root, 'Figure ' + fig_name + ' sgRNA ' + str(idx + 1), - run_data['results']['refs'][amplicon_name]['plot_' + fig + '_captions'][idx], - run_data['results']['refs'][amplicon_name]['plot_' + fig + '_datas'][idx], - this_fig_names, amplicon_figures, crispresso_folder) - this_sgRNA_based_fig_names[fig] = this_fig_names - - figures['names'][amplicon_name] = amplicon_figures['names'] - figures['sgRNA_based_names'][amplicon_name] = this_sgRNA_based_fig_names - - figures['locs'][amplicon_name] = amplicon_figures['locs'] - figures['titles'][amplicon_name] = amplicon_figures['titles'] - figures['captions'][amplicon_name] = amplicon_figures['captions'] - figures['datas'][amplicon_name] = amplicon_figures['datas'] - figures['htmls'][amplicon_name] = amplicon_figures['htmls'] - data = {'amplicons': amplicons, 'figures': figures} - return data - - -def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, web_version=False): - # dicts for each amplicon fig_names[amp_name] = [list of fig names] - # fig_locs[amp_name][fig_name] = figure location - # print('crispresso_report file: ' + crispresso_report_file + ' crispresso_folder : ' + crispresso_folder + ' root: ' + _ROOT) - data = assemble_figs(run_data, crispresso_folder) - - report_display_name = "" - if run_data['running_info']['args'].name != "": - report_display_name = run_data['running_info']['args'].name - - # find path between the report and the data (if the report is in another directory vs in the same directory as the data) - crispresso_data_path = os.path.relpath(crispresso_folder, os.path.dirname(crispresso_report_file)) - if crispresso_data_path == ".": - crispresso_data_path = "" - else: - crispresso_data_path += "/" - - report_data = { - 'amplicons': data['amplicons'], - 'figures': data['figures'], - 'run_data': run_data, - 'report_display_name': report_display_name, - 'crispresso_data_path': crispresso_data_path, - } - - j2_env = Environment(loader=FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates'))) - - # dest_dir = os.path.dirname(crispresso_report_file) - # shutil.copy2(os.path.join(_ROOT,'templates','CRISPResso_justcup.png'),dest_dir) - # shutil.copy2(os.path.join(_ROOT,'templates','favicon.ico'),dest_dir) - - with open(crispresso_report_file, 'w') as outfile: - outfile.write(render_template( - 'report.html', j2_env, report_data=report_data, - )) - - -def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info, batch_folder, _ROOT): - batch_names = crispresso2_info['results']['completed_batch_arr'] - display_names = crispresso2_info['results']['batch_input_names'] - - window_nuc_pct_quilts = crispresso2_info['results']['general_plots']['window_nuc_pct_quilt_plot_names'] - nuc_pct_quilts = crispresso2_info['results']['general_plots']['nuc_pct_quilt_plot_names'] - - window_nuc_conv_plots = crispresso2_info['results']['general_plots']['window_nuc_conv_plot_names'] - nuc_conv_plots = crispresso2_info['results']['general_plots']['nuc_conv_plot_names'] - - summary_plot_names = [] - if 'summary_plot_names' in crispresso2_info['results']['general_plots']: - summary_plot_names = crispresso2_info['results']['general_plots']['summary_plot_names'] - summary_plot_titles = {} - if 'summary_plot_titles' in crispresso2_info['results']['general_plots']: - summary_plot_titles = crispresso2_info['results']['general_plots']['summary_plot_titles'] - summary_plot_labels = {} - if 'summary_plot_labels' in crispresso2_info['results']['general_plots']: - summary_plot_labels = crispresso2_info['results']['general_plots']['summary_plot_labels'] - summary_plot_datas = {} - if 'summary_plot_datas' in crispresso2_info['results']['general_plots']: - summary_plot_datas = crispresso2_info['results']['general_plots']['summary_plot_datas'] - - allele_modification_heatmap_plot = {} - if 'allele_modification_heatmap_plot_names' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_names'] - else: - allele_modification_heatmap_plot['names'] = [] - if 'allele_modification_heatmap_plot_paths' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_paths'] - else: - allele_modification_heatmap_plot['paths'] = {} - if 'allele_modification_heatmap_plot_titles' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_titles'] - else: - allele_modification_heatmap_plot['titles'] = [] - if 'allele_modification_heatmap_plot_labels' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_labels'] - else: - allele_modification_heatmap_plot['labels'] = {} - if 'allele_modification_heatmap_plot_datas' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_datas'] - else: - allele_modification_heatmap_plot['datas'] = {} - - allele_modification_line_plot = {} - if 'allele_modification_line_plot_names' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_names'] - else: - allele_modification_line_plot['names'] = [] - if 'allele_modification_line_plot_paths' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_paths'] - else: - allele_modification_line_plot['paths'] = {} - if 'allele_modification_line_plot_titles' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_titles'] - else: - allele_modification_line_plot['titles'] = [] - if 'allele_modification_line_plot_labels' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_labels'] - else: - allele_modification_line_plot['labels'] = {} - if 'allele_modification_line_plot_datas' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_datas'] - else: - allele_modification_line_plot['datas'] = {} - - allele_modification_heatmap_plot['htmls'] = {} - for heatmap_plot_name, heatmap_plot_path in allele_modification_heatmap_plot['paths'].items(): - with open(heatmap_plot_path) as fh: - allele_modification_heatmap_plot['htmls'][heatmap_plot_name] = fh.read() - - allele_modification_line_plot['htmls'] = {} - for line_plot_name, line_plot_path in allele_modification_line_plot['paths'].items(): - with open(line_plot_path) as fh: - allele_modification_line_plot['htmls'][line_plot_name] = fh.read() - - #find path between the report and the data (if the report is in another directory vs in the same directory as the data) - crispresso_data_path = os.path.relpath(batch_folder, os.path.dirname(crispressoBatch_report_file)) - if crispresso_data_path == ".": - crispresso_data_path = "" - else: - crispresso_data_path += "/"; - - sub_html_files = {} - run_names = [] - for name in batch_names: - display_name = display_names[name] - sub_folder = 'CRISPResso_on_' + name - crispresso_folder = os.path.join(batch_folder, sub_folder) - run_data = CRISPRessoShared.load_crispresso_info(crispresso_folder) - if 'running_info' not in run_data: - raise Exception('CRISPResso run %s has no report. Cannot add to batch report.' % sub_folder) - - this_sub_html_file = sub_folder + ".html" - if run_data['running_info']['args'].place_report_in_output_folder: - this_sub_html_file = os.path.join(sub_folder, run_data['running_info']['report_filename']) - sub_html_files[display_name] = this_sub_html_file - - run_names.append(display_name) - - output_title = 'CRISPResso Batch Output' - if crispresso2_info['running_info']['args'].name != '': - output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - - make_multi_report( - run_names, - sub_html_files, - crispressoBatch_report_file, - batch_folder, - _ROOT, - output_title, - 'batch', - summary_plots={ - 'names': summary_plot_names, - 'titles': summary_plot_titles, - 'labels': summary_plot_labels, - 'datas': summary_plot_datas, - }, - window_nuc_pct_quilts=window_nuc_pct_quilts, - nuc_pct_quilts=nuc_pct_quilts, - window_nuc_conv_plots=window_nuc_conv_plots, - nuc_conv_plots=nuc_conv_plots, - allele_modification_heatmap_plot=allele_modification_heatmap_plot, - allele_modification_line_plot=allele_modification_line_plot, - ) - - -def make_pooled_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): - names_arr = crispresso2_info['results']['good_region_names'] - output_title = 'CRISPResso Pooled Output' - if crispresso2_info['running_info']['args'].name != '': - output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'pooled') - - -def make_compare_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): - names_arr = [] - output_title = 'CRISPResso Compare Output' - if crispresso2_info['running_info']['args'].name != '': - output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'compare') - - -def make_meta_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): - names_arr = crispresso2_info['meta_names_arr'] - input_names = crispresso2_info['meta_input_names'] - output_title = 'CRISPresso Meta Output' - if crispresso2_info['running_info']['args'].name != '': - output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'meta', - display_names=input_names) - - -def make_wgs_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT): - names_arr = crispresso2_info['results']['good_region_names'] - output_title = 'CRISPResso WGS Output' - if crispresso2_info['running_info']['args'].name != '': - output_title += '
{0}'.format(crispresso2_info['running_info']['args'].name) - make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'wgs') - - -def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, crispresso_report_file, folder, _ROOT, crispresso_tool, - display_names=None): - """ - Prepares information to make a report of multiple CRISPResso runs - like CRISPRessoWGS or CRISPRessoPooled - - Parameters: - crispresso2_info (dict): information from the crispresso multi run - names_arr (arr of strings): Names of the crispresso runs - report_name (string): text to be shown at top of report - crispresso_report_file (string): path to write report to - folder (string): folder containing crispresso runs - _ROOT (string): location of crispresso assets (images, templates, etc) - display_names (dict): report_name->display_name; Titles to be shown for crispresso runs (if different from names_arr, e.g. if display_names have spaces or bad chars, they won't be the same as names_arr) - - Returns: - Nothin - """ - - summary_plot_names = [] - if 'summary_plot_names' in crispresso2_info['results']['general_plots']: - summary_plot_names = crispresso2_info['results']['general_plots']['summary_plot_names'] - summary_plot_titles = {} - if 'summary_plot_titles' in crispresso2_info['results']['general_plots']: - summary_plot_titles = crispresso2_info['results']['general_plots']['summary_plot_titles'] - summary_plot_labels = {} - if 'summary_plot_labels' in crispresso2_info['results']['general_plots']: - summary_plot_labels = crispresso2_info['results']['general_plots']['summary_plot_labels'] - summary_plot_datas = {} - if 'summary_plot_datas' in crispresso2_info['results']['general_plots']: - summary_plot_datas = crispresso2_info['results']['general_plots']['summary_plot_datas'] - - run_names = [] - sub_html_files = {} - sub_2a_labels = {} - sub_2a_pdfs = {} - - for name in names_arr: - display_name = name - if display_names is not None: - display_name = display_names[name] - - folder_name = 'CRISPResso_on_%s' % name - sub_folder = os.path.join(folder, folder_name) - run_data = CRISPRessoShared.load_crispresso_info(sub_folder) - if 'running_info' not in run_data: - raise Exception('CRISPResso run %s has no report. Cannot add to report.' % sub_folder) - - run_names.append(display_name) - - this_sub_html_file = os.path.basename(folder_name) + ".html" - if run_data['running_info']['args'].place_report_in_output_folder: - this_sub_html_file = os.path.join(os.path.basename(sub_folder), run_data['running_info']['report_filename']) - sub_html_files[display_name] = this_sub_html_file - - this_sub_2a_labels = [] - this_sub_2a_pdfs = [] - for ref_name in run_data['results']['ref_names']: - if 'plot_2a_root' in run_data['results']['refs'][ref_name]: - pdf_file = run_data['results']['refs'][ref_name]['plot_2a_root'] + ".pdf" - if os.path.exists(pdf_file): - this_sub_2a_pdfs.append(run_data['results']['refs'][ref_name]['plot_2a_root'] + ".pdf") - this_sub_2a_labels.append("Nucleotide distribution across " + ref_name) - - sub_2a_labels[display_name] = this_sub_2a_labels - sub_2a_pdfs[display_name] = this_sub_2a_pdfs - - make_multi_report( - run_names, - sub_html_files, - crispresso_report_file, - folder, - _ROOT, - report_name, - crispresso_tool, - summary_plots={ - 'names': summary_plot_names, - 'titles': summary_plot_titles, - 'labels': summary_plot_labels, - 'datas': summary_plot_datas, - }, - ) - - -def make_multi_report( - run_names, - sub_html_files, - crispresso_multi_report_file, - crispresso_folder, - _ROOT, - report_name, - crispresso_tool, - window_nuc_pct_quilts=[], - nuc_pct_quilts=[], - window_nuc_conv_plots=[], - nuc_conv_plots=[], - summary_plots={ - 'names': [], - 'titles': [], - 'labels': [], - 'datas': [], - }, - compact_plots_to_show={}, - allele_modification_heatmap_plot={}, - allele_modification_line_plot={}, -): - """ - Makes an HTML report for a run containing multiple crispresso runs - - Parameters: - run_names (arr of strings): names of runs - sub_html_files (dict): dict of run_name->file_loc - crispresso_multi_report_file (string): path of file to write to - report_name (string): description of report type to be shown at top of report - crispresso_folder (string): absolute path to the crispresso output - _ROOT (string): absolute path to the crispresso executable - summary_plots (dict): a dict with the following keys: - names (list): list of plot names - keys for following dicts - titles (dict): dict of plot_name->plot_title - labels (dict): dict of plot_name->plot_label - datas (dict): dict of plot_name->[(datafile_description, data_filename), ...] - compact_plots_to_show (dict): name=>{'href': path to target(report) when user clicks on image, 'img': path to png image to show} - allele_modification_heatmap_plot (dict): a dict with the following keys: - names (list): list of plot names for heatmaps, keys for dicts below - htmls (dict): dict of plot_name->HTML for the plot - titles (dict): dict of plot_name->plot_title - labels (dict): dict of plot_name->plot_label - datas (dict): dict of plot_name->[(datafile_description, data_filename), ...] - """ - - def dirname(path): - return os.path.basename(os.path.dirname(path)) - - def fill_default(dictionary, key, default_type=list): - if key not in dictionary: - dictionary[key] = default_type() - - j2_env = Environment( - loader=FileSystemLoader(os.path.join(_ROOT, 'CRISPRessoReports', 'templates')), - ) - j2_env.filters['dirname'] = dirname - if crispresso_tool == 'batch': - template = 'batchReport.html' - elif crispresso_tool == 'pooled': - template = 'pooledReport.html' - elif crispresso_tool == 'wgs': - template = 'wgsReport.html' - else: - template = 'multiReport.html' - - crispresso_data_path = os.path.relpath( - crispresso_folder, os.path.dirname(crispresso_multi_report_file), - ) - if crispresso_data_path == ".": - crispresso_data_path = "" - else: - crispresso_data_path += "/" - - dictionaries = [ - allele_modification_heatmap_plot, allele_modification_line_plot, - ] - keys_and_default_types = [ - ('names', list), - ('htmls', dict), - ('titles', list), - ('labels', dict), - ('datas', dict), - ] - for dictionary in dictionaries: - for key, default_type in keys_and_default_types: - fill_default( - dictionary, - key, - default_type, - ) - web = False - if not web: - for html in sub_html_files: - sub_html_files[html] = crispresso_data_path + sub_html_files[html] - with open(crispresso_multi_report_file, 'w') as outfile: - outfile.write(render_template( - template, - j2_env, - window_nuc_pct_quilts=window_nuc_pct_quilts, - nuc_pct_quilts=nuc_pct_quilts, - window_nuc_conv_plots=window_nuc_conv_plots, - nuc_conv_plots=nuc_conv_plots, - crispresso_data_path=crispresso_data_path, - report_data={ - 'names': summary_plots['names'], - 'titles': summary_plots['titles'], - 'labels': summary_plots['labels'], - 'datas': summary_plots['datas'], - 'htmls': [], - 'crispresso_data_path': crispresso_data_path, - }, - run_names=run_names, - sub_html_files=sub_html_files, - report_name=report_name, - compact_plots_to_show=compact_plots_to_show, - allele_modification_heatmap_plot_names=allele_modification_heatmap_plot['names'], - allele_modification_heatmap_plot_htmls=allele_modification_heatmap_plot['htmls'], - allele_modification_heatmap_plot_titles=allele_modification_heatmap_plot['titles'], - allele_modification_heatmap_plot_labels=allele_modification_heatmap_plot['labels'], - allele_modification_heatmap_plot_datas=allele_modification_heatmap_plot['datas'], - allele_modification_line_plot_names=allele_modification_line_plot['names'], - allele_modification_line_plot_htmls=allele_modification_line_plot['htmls'], - allele_modification_line_plot_titles=allele_modification_line_plot['titles'], - allele_modification_line_plot_labels=allele_modification_line_plot['labels'], - allele_modification_line_plot_datas=allele_modification_line_plot['datas'], - )) - - -def make_aggregate_report( - crispresso2_info, - report_name, - crispresso_report_file, - crispresso_report_folder, - _ROOT, - folder_arr, - crispresso_html_reports, - compact_plots_to_show={}, - display_names=None, -): - """ - Prepares information to make a report of a CRISPRessoAggregate run - - Parameters: - crispresso2_info (dict): information from the crispresso aggregate run - report_name (string): text to be shown at top of report - crispresso_report_file (string): path to write report to - crispresso_report_folder (string): path containing aggregated plots, etc. - _ROOT (string): location of crispresso assets (images, templates, etc) - folder_arr (arr of strings): paths to the aggregated crispresso folders - crispresso_html_reports (dict): folder->html_path; Paths to the aggregated crispresso run html reports - compact_plots_to_show (dict): name=>{'href': path to target(report) when user clicks on image, 'img': path to png image to show} - display_names (dict): folder->display_name; Titles to be shown for crispresso runs (if different from names_arr, e.g. if display_names have spaces or bad chars, they won't be the same as names_arr) - - Returns: - Nothin - """ - summary_plots = {} - if 'summary_plot_names' in crispresso2_info['results']['general_plots']: - summary_plots['names'] = crispresso2_info['results']['general_plots']['summary_plot_names'] - else: - summary_plots['names'] = [] - if 'summary_plot_titles' in crispresso2_info['results']['general_plots']: - summary_plots['titles'] = crispresso2_info['results']['general_plots']['summary_plot_titles'] - else: - summary_plots['titles'] = {} - if 'summary_plot_labels' in crispresso2_info['results']['general_plots']: - summary_plots['labels'] = crispresso2_info['results']['general_plots']['summary_plot_labels'] - else: - summary_plots['labels'] = {} - if 'summary_plot_datas' in crispresso2_info['results']['general_plots']: - summary_plots['datas'] = crispresso2_info['results']['general_plots']['summary_plot_datas'] - else: - summary_plots['datas'] = {} - - allele_modification_heatmap_plot = {} - if 'allele_modification_heatmap_plot_names' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_names'] - else: - allele_modification_heatmap_plot['names'] = [] - if 'allele_modification_heatmap_plot_paths' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_paths'] - else: - allele_modification_heatmap_plot['paths'] = {} - if 'allele_modification_heatmap_plot_titles' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_titles'] - else: - allele_modification_heatmap_plot['titles'] = {} - if 'allele_modification_heatmap_plot_labels' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_labels'] - else: - allele_modification_heatmap_plot['labels'] = {} - if 'allele_modification_heatmap_plot_datas' in crispresso2_info['results']['general_plots']: - allele_modification_heatmap_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_heatmap_plot_datas'] - else: - allele_modification_heatmap_plot['datas'] = {} - - allele_modification_line_plot = {} - if 'allele_modification_line_plot_names' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['names'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_names'] - else: - allele_modification_line_plot['names'] = [] - if 'allele_modification_line_plot_paths' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['paths'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_paths'] - else: - allele_modification_line_plot['paths'] = {} - if 'allele_modification_line_plot_titles' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['titles'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_titles'] - else: - allele_modification_line_plot['titles'] = {} - if 'allele_modification_line_plot_labels' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['labels'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_labels'] - else: - allele_modification_line_plot['labels'] = {} - if 'allele_modification_line_plot_datas' in crispresso2_info['results']['general_plots']: - allele_modification_line_plot['datas'] = crispresso2_info['results']['general_plots']['allele_modification_line_plot_datas'] - else: - allele_modification_line_plot['datas'] = {} - - window_nuc_pct_quilts = [] - if 'window_nuc_pct_quilt_plot_names' in crispresso2_info['results']['general_plots']: - window_nuc_pct_quilts = crispresso2_info['results']['general_plots']['window_nuc_pct_quilt_plot_names'] - nuc_pct_quilts = [] - if 'nuc_pct_quilt_plot_names' in crispresso2_info['results']['general_plots']: - nuc_pct_quilts = crispresso2_info['results']['general_plots']['nuc_pct_quilt_plot_names'] - - run_names = [] - sub_html_files = {} - - for idx, folder in enumerate(folder_arr): - display_name = folder - if display_names is not None: - display_name = display_names[folder] - - run_names.append(display_name) - sub_html_file = os.path.relpath(crispresso_html_reports[folder], crispresso_report_folder) - sub_html_files[display_name] = sub_html_file - - for compact_plot in compact_plots_to_show: - old_href = compact_plots_to_show[compact_plot]['href'] - compact_plots_to_show[compact_plot]['href'] = os.path.relpath(old_href, crispresso_report_folder) - old_img = compact_plots_to_show[compact_plot]['img'] - compact_plots_to_show[compact_plot]['img'] = os.path.relpath(old_img, crispresso_report_folder) - - allele_modification_heatmap_plot['htmls'] = {} - for heatmap_plot_name, heatmap_plot_path in allele_modification_heatmap_plot['paths'].items(): - with open(heatmap_plot_path) as fh: - allele_modification_heatmap_plot['htmls'][heatmap_plot_name] = fh.read() - - allele_modification_line_plot['htmls'] = {} - for line_plot_name, line_plot_path in allele_modification_line_plot['paths'].items(): - with open(line_plot_path) as fh: - allele_modification_line_plot['htmls'][line_plot_name] = fh.read() - - make_multi_report( - run_names, - sub_html_files, - crispresso_report_file, - crispresso_report_folder, - _ROOT, - report_name, - window_nuc_pct_quilts=window_nuc_pct_quilts, - nuc_pct_quilts=nuc_pct_quilts, - summary_plots=summary_plots, - compact_plots_to_show=compact_plots_to_show, - allele_modification_heatmap_plot=allele_modification_heatmap_plot, - allele_modification_line_plot=allele_modification_line_plot, - ) diff --git a/templates/CRISPResso_justcup.png b/templates/CRISPResso_justcup.png deleted file mode 100644 index 3116c48c394f23cf37669c6dbb92928ef0d88b9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42782 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 diff --git a/templates/batchReport.html b/templates/batchReport.html deleted file mode 100644 index d02c6269..00000000 --- a/templates/batchReport.html +++ /dev/null @@ -1,163 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
- -
-
- - {% if run_names|length > 0 %} -
-
-
{{report_name}}
-
-
-
- {% for run_name in run_names %} - {{run_name}} - {% endfor %} -
-
-
- {% endif %} - - {% if window_nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages around guides
-
-
- {% for plot_name in window_nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages in the entire amplicon
-
-
- {% for plot_name in nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if window_nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases around guides
-
-
- {% for plot_name in window_nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases in the entire amplicon
-
-
- {% for plot_name in nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - -
- -
- - - - {# data bit for web version: #} - {# -

Data: {{data_label}}

- #} -
{# jumbotron_content #} -
{# jumbrotron #} - - {# column #} - -
- -{% endblock %} - -{% block foot %} -{% endblock %} diff --git a/templates/favicon.ico b/templates/favicon.ico deleted file mode 100644 index 8aed2d0743b52f12c1f0f8b2b4c439ba77091af3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmbVMTWeE65MIGIUy2Vt`{*xIQTtGpYE@zjwT6~P+tO3xNz+rB6BBFO#3;0l0Sg5a zZAl=|kQxgi_XiV_ko)E9&Xx@^1Pab!cV@nwZ)Rt5au~b9pOF#9_nYkQRmN^G#%}S& zA&y+&TrtMau3x)Y!si1jMS7+{#1gs$u8 zbUGr3j2X-&@p8G0S4Jb0RSQPWS&7j;UxRtyjV~aI9)ri>NaQ} z>~Oeuu(+b&=h3fA`*^3SaBOd3!|A}9U5943;giRWWz~!c!wYD(4dnBAQA^%g>LQ<) zs%h}-?+MOFw+owmecsy@dCWZbuGb5@(>av?=j;rMMTMfi$Kz)c7#knQqo+?`G?`%A zbYkx98F-lC8jXMI_VcApG3|C6>2zAuA-}}uB7YyLWxUk& zdL5Ze2Dw~LK*?khg+c+OoBUm*vs5Z2Y{?-l?@je8m5Ml`8pI$zXSiP&jEy - - - CRISPResso2 - - - - - - - - - - - - - - - - - - - - - - - {% if current_user is defined %} - - {% else %} - - {% endif %} - - - - - {% block head %}{% endblock %} - - - - - {% if current_user is defined %} -
- {{ self.help_block() }} -
- - {% with messages = get_flashed_messages(with_categories=true) %} - {% if messages %} - {% for category, message in messages %} - {% if category == "error" %} - - {% else %} - - {% endif %} - {% endfor %} - {% endif %} - {% endwith %} - {% endif %} - - {# if default user (normal crispresso mode) #} - {% if current_user == null or not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} - -
-
-
- {% if current_user is defined %} -
- {% else %} -
- {% endif %} -
-
-

CRISPResso2

-

Analysis of genome editing outcomes from deep sequencing data

-
-
-
-
- - - {% else %} - {# if doing user sessions #} - -
- {% endif %} - -
-
-
-
- {% block help_block %} {% endblock %} -
-
-
-
- - {% block content %}{% endblock %} - - {% if current_user is defined and (not current_user.is_anonymous and current_user.username == "DEFAULTUSER") %} -
-
- -
-
- {% else %} -
-
- -
-
- {% endif %} -
- - - - - - - {% block foot %}{% endblock %} - - - diff --git a/templates/multiReport.html b/templates/multiReport.html deleted file mode 100644 index 8e8d83ca..00000000 --- a/templates/multiReport.html +++ /dev/null @@ -1,265 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
- -
-
- - {% if run_names|length > 0 %} -
-
-
{{report_name}}
-
-
-
- {% for run_name in run_names %} - {{run_name}} - {% endfor %} -
-
-
- {% endif %} - - {% if window_nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages around guides
-
-
- {% for plot_name in window_nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages in the entire amplicon
-
-
- {% for plot_name in nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if window_nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases around guides
-
-
- {% for plot_name in window_nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases in the entire amplicon
-
-
- {% for plot_name in nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} - - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - {% if allele_modification_heatmap_plot_names|length > 0 %} - {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} - {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} - {% set modification_type = heatmap_plot_name.split('_')[3] %} -
-
-
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
- -
-
-
-
- {{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} - - {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
-
- {{allele_modification_line_plot_htmls[line_plot_name]}} - - {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
-
-
-
- - {% endfor %} - - - - {% endif %} - - {% if compact_plots_to_show|length > 0 %} -
-
-
Summary Plots
-
-
-
- {% for compact_plot in compact_plots_to_show %} - - {% endfor %} -
-
-
- {% endif %} - - -
- -
- -
{# jumbotron_content #} -
{# jumbrotron #} - -
{# column #} - -
-{% endblock %} - -{% block foot %} -{% endblock %} diff --git a/templates/pooledReport.html b/templates/pooledReport.html deleted file mode 100644 index f4550e82..00000000 --- a/templates/pooledReport.html +++ /dev/null @@ -1,101 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
- -
-
- - {% if run_names|length > 0 %} -
-
-
{{report_name}}
-
-
-
- {% for region_name in run_names %} - {{region_name}} - {% endfor %} -
-
-
- {% endif %} - - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - - {# data bit for web version: #} - {# -

Data: {{data_label}}

- #} -
{# jumbotron_content #} -
{# jumbrotron #} - -
{# column #} - -
-
-{% endblock %} - -{% block foot %} -{% endblock %} diff --git a/templates/report.html b/templates/report.html deleted file mode 100644 index fb755d18..00000000 --- a/templates/report.html +++ /dev/null @@ -1,693 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
-
-
-
- {% if report_data['report_display_name'] != '' %} -
{{report_data['report_display_name']}}
- {% endif %} -
CRISPResso2 run information
- -
-
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1a')}} -
- {{ render_partial('shared/partials/log_params.html', report_data=report_data) }} -
-
-
- -
-
-
Allele assignments
- -
-
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1b')}} -
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1c')}} -
- {% if report_data['figures']['locs']['plot_1d'] %} -
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1d')}} -
- {% endif %} -
-
-
{# end card #} - - {# start global coding sequence report #} - {% if report_data['figures']['locs']['plot_5a'] %} -
-
-
Global frameshift analysis
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5a')}} -
-
- {% endif %} - - {% if report_data['figures']['locs']['plot_6a'] %} -
-
-
Global frameshift mutagenesis profiles
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6a')}} -
-
- {% endif %} - - {% if report_data['figures']['locs']['plot_8a'] %} -
-
-
Global splicing analysis
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a')}} -
-
- {% endif %} - {# end of global coding sequence analysis #} - - {# start hdr summary #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
HDR summary plot
- {% else %} -
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', amplicon_name=report_data.amplicons[0])}} -
-
- {% endif %} - {# end HDR summary #} - - {# start prime editing report #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing report
- {% else %} -
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', amplicon_name=report_data.amplicons[0])}} -
-
- {% endif %} - - {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing summary plots at analysis positions
- {% else %} -
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} -
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=report_data.amplicons[0])}} -
- {% endfor %} -
-
- {% endif %} - {# end plot 11b for prime editing #} - - {% if report_data['figures']['locs']['plot_11c'] %} -
-
-
Scaffold insertions
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c')}} -
-
- {% endif %} - {# end prime editing section #} - - {% if report_data.amplicons|length == 1 %} -
{# if only one amplicon, just a normal div #} - {% else %} - {# If there is more than one amplicon, print a navigation to show each amplicon #} -

Reads are aligned to each amplicon sequence separately. Quantification and visualization of these reads are shown for each amplicon below:

-
-
-
Amplicons
- -
- {% endif %} {# end if report contains more than one amplicon #} - - - {% if report_data.amplicons|length == 1 %} {# if only one amplicon, just a normal div #} -
- {% else %} - {# jumbotron_content #} -
{# jumbrotron #} -
{# column #} -
- -
-{% endblock %} - -{% block foot %} - -{% endblock %} diff --git a/templates/shared/partials/fig_reports.html b/templates/shared/partials/fig_reports.html deleted file mode 100644 index 6f7e448e..00000000 --- a/templates/shared/partials/fig_reports.html +++ /dev/null @@ -1,31 +0,0 @@ -
- {% if amplicon_name is defined %} - {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'][amplicon_name] %} - {{report_data['figures']['htmls'][amplicon_name][fig_name]|safe}} - {% else %} - {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} - - {% else %} - - {% endif %} - {% endif %} - - {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} -

Data: {{data_label}}

- {% endfor %} - {% else %} - {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'] %} - {{report_data['figures']['htmls'][fig_name]|safe}} - {% else %} - {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} - - {% else %} - - {% endif %} - {% endif %} - - {% for (data_label,data_path) in report_data['figures']['datas'][fig_name] %} -

Data: {{data_label}}

- {% endfor %} - {% endif %} -
\ No newline at end of file diff --git a/templates/shared/partials/fig_summaries.html b/templates/shared/partials/fig_summaries.html deleted file mode 100644 index e4e3297a..00000000 --- a/templates/shared/partials/fig_summaries.html +++ /dev/null @@ -1,11 +0,0 @@ -
- {% if report_data['htmls'][plot_name] %} - {{report_data['htmls'][plot_name]|safe}} - {% else %} - - {% endif %} - - {% for (data_label,data_path) in report_data['datas'][plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
diff --git a/templates/shared/partials/log_params.html b/templates/shared/partials/log_params.html deleted file mode 100644 index ad035ae3..00000000 --- a/templates/shared/partials/log_params.html +++ /dev/null @@ -1,11 +0,0 @@ -
-

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

-

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

-

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

- {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} -

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

- {% endif %} -

Command used:

{{report_data['run_data']['running_info']['command_used']}}

-

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

-

Running log

-
diff --git a/templates/wgsReport.html b/templates/wgsReport.html deleted file mode 100644 index 0a5a1277..00000000 --- a/templates/wgsReport.html +++ /dev/null @@ -1,99 +0,0 @@ -{% extends "layout.html" %} -{% block head %} - - -{% endblock %} - -{% block content %} -
-
-
- -
-
- -
-
-
{{report_name}}
-
-
-
- {% for region_name in run_names %} - {{region_name}} - {% endfor %} -
-
-
- - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
-
- {% endfor %} - {% endif %} - - - {# data bit for web version: #} - {# -

Data: {{data_label}}

- #} -
{# jumbotron_content #} -
{# jumbrotron #} - -
{# column #} - -
-
-{% endblock %} - -{% block foot %} -{% endblock %} From 5cd6d2707e6c95a20939531f1be770be4169625b Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Fri, 23 Sep 2022 11:48:32 -0600 Subject: [PATCH 18/33] Final style fixes, color circles for style files --- templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/layout.html b/templates/layout.html index dba520de..d72c7c3a 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -184,7 +184,7 @@

Analysis of genome editing ou
-
+
{% block help_block %} {% endblock %}
From 2f70855b57de16584ee0fe85f4f30c1a0d13cf97 Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Wed, 28 Sep 2022 10:21:16 -0600 Subject: [PATCH 19/33] Add spacing around body and footer tags --- templates/layout.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/layout.html b/templates/layout.html index d72c7c3a..ff61410f 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -87,9 +87,9 @@ - + {% if current_user is defined %} -
+
{{ self.help_block() }}
@@ -135,7 +135,7 @@

Analysis of genome editing ou {% else %} {# if doing user sessions #} -

- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a')}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a', width='40%')}}
{% endif %} @@ -160,7 +160,7 @@
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
{% endif %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', amplicon_name=report_data.amplicons[0])}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', width='40%', amplicon_name=report_data.amplicons[0])}}
{% endif %} @@ -177,7 +177,7 @@
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', amplicon_name=report_data.amplicons[0])}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', width='40%', amplicon_name=report_data.amplicons[0])}}
{% endif %} @@ -194,7 +194,7 @@
Prime editing summary plots at analysis positions (aligned to {{report_data.
{% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=report_data.amplicons[0])}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='40%', amplicon_name=report_data.amplicons[0])}}
{% endfor %}
@@ -208,7 +208,7 @@
Prime editing summary plots at analysis positions (aligned to {{report_data.
Scaffold insertions
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c')}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c', width='40%')}}
{% endif %} @@ -288,7 +288,7 @@
Nucleotide composition for {{amplicon_name}}
{% if report_data['figures']['sgRNA_based_names'][amplicon_name] and report_data['figures']['sgRNA_based_names'][amplicon_name]['2b']%} {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['2b'] %} - {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='80%', amplicon_name=amplicon_name)}} {% endfor %} {% endif %} @@ -318,13 +318,13 @@
Modification lengths for {{amplicon_name}}
{% if report_data['figures']['locs'][amplicon_name]['plot_3a'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_3a', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_3a', width='40%', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_3b'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_3b', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_3b', width='100%', amplicon_name=amplicon_name)}}
{% endif %}
@@ -375,35 +375,35 @@
Indel characterization for {{amplicon_name}}
{% if report_data['figures']['locs'][amplicon_name]['plot_4a'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4a', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4a', width='40%', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4b'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4b', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4b', width='40%', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4c'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4c', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4c', width='40%', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4d'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4d', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4d', width='80%', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4e'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4e', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4e', width='40%', amplicon_name=amplicon_name)}}
{% endif %} {% if report_data['figures']['locs'][amplicon_name]['plot_4f'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4f', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4f', width='40%', amplicon_name=amplicon_name)}}
{% endif %}
@@ -421,7 +421,7 @@
Frameshift analysis for {{amplicon_name}}
{% endif %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5', width='40%', amplicon_name=amplicon_name)}}
{% endif %} @@ -436,7 +436,7 @@
Frameshift mutagenesis profiles for {{amplicon_name}}
{% endif %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6', width='40%', amplicon_name=amplicon_name)}}
{% endif %} @@ -451,7 +451,7 @@
Coding mutations for {{amplicon_name}}
{% endif %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_7', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_7', width='40%', amplicon_name=amplicon_name)}}
{% endif %} @@ -466,7 +466,7 @@
Splicing for {{amplicon_name}}
{% endif %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8', width='40%', amplicon_name=amplicon_name)}}
{% endif %} @@ -483,7 +483,7 @@
Allele plots for {{amplicon_name}}
{% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['9'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='100%', amplicon_name=amplicon_name)}}
{% endfor %}
@@ -526,21 +526,21 @@
Base editing for {{amplicon_name}}
{% if report_data['figures']['locs'][amplicon_name]['plot_10c'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10a', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10a', width='80%', amplicon_name=amplicon_name)}}
- - {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10b', amplicon_name=amplicon_name)}} - {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10c', amplicon_name=amplicon_name)}} + + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10b', width='50%', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10c', width='50%', amplicon_name=amplicon_name)}}
{% else %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10a', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10a', width='80%', amplicon_name=amplicon_name)}}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10b', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10b', width='50%', amplicon_name=amplicon_name)}}
{% endif %} @@ -548,7 +548,7 @@
Base editing for {{amplicon_name}}
{% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10d'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='80%', amplicon_name=amplicon_name)}}
{% endfor %}
@@ -557,7 +557,7 @@
Base editing for {{amplicon_name}}
{% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10e'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='80%', amplicon_name=amplicon_name)}}
{% endfor %}
@@ -566,17 +566,17 @@
Base editing for {{amplicon_name}}
{% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10f'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10f', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='80%', amplicon_name=amplicon_name)}}
{% endfor %} {% for fig_name in report_data['figures']['sgRNA_based_names'][amplicon_name]['10g'] %}
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_10g', amplicon_name=amplicon_name)}} + {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='80%', amplicon_name=amplicon_name)}}
{% endfor %}
+ {% endif %} - {% endif %} {# end card #} {% endif %} {# end base editing card #} diff --git a/templates/shared/partials/fig_reports.html b/templates/shared/partials/fig_reports.html index 6f7e448e..e9057e16 100644 --- a/templates/shared/partials/fig_reports.html +++ b/templates/shared/partials/fig_reports.html @@ -1,13 +1,10 @@
+
{% if amplicon_name is defined %} {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'][amplicon_name] %} {{report_data['figures']['htmls'][amplicon_name][fig_name]|safe}} {% else %} - {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} - - {% else %} - - {% endif %} + {% endif %} {% for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} @@ -17,15 +14,12 @@ {% if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'] %} {{report_data['figures']['htmls'][fig_name]|safe}} {% else %} - {% if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c'] %} - - {% else %} - - {% endif %} + {% endif %} {% for (data_label,data_path) in report_data['figures']['datas'][fig_name] %}

Data: {{data_label}}

{% endfor %} {% endif %} +
\ No newline at end of file From e7ef285dbc92b309b674c8c3f54b88cb8e07a2a0 Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Wed, 28 Sep 2022 11:31:42 -0600 Subject: [PATCH 21/33] Fix hamburger menu and add -bs- to data-target and data-toggle --- templates/batchReport.html | 2 +- templates/layout.html | 2 +- templates/multiReport.html | 2 +- templates/pooledReport.html | 2 +- templates/wgsReport.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/batchReport.html b/templates/batchReport.html index d02c6269..cb9d4aa0 100644 --- a/templates/batchReport.html +++ b/templates/batchReport.html @@ -148,7 +148,7 @@
{{report_data['titles'][plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#} {# jumbotron_content #} {# jumbrotron #} diff --git a/templates/layout.html b/templates/layout.html index ff61410f..1e37522a 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -143,7 +143,7 @@

Analysis of genome editing ou {{config['BANNER_TEXT']}} - diff --git a/templates/multiReport.html b/templates/multiReport.html index 8e8d83ca..44d66112 100644 --- a/templates/multiReport.html +++ b/templates/multiReport.html @@ -241,7 +241,7 @@

Summary Plots
{% for compact_plot in compact_plots_to_show %} - + {% endfor %}
diff --git a/templates/pooledReport.html b/templates/pooledReport.html index f4550e82..e6817601 100644 --- a/templates/pooledReport.html +++ b/templates/pooledReport.html @@ -86,7 +86,7 @@
{{report_data['titles'][plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#} {# jumbotron_content #} {# jumbrotron #} diff --git a/templates/wgsReport.html b/templates/wgsReport.html index 0a5a1277..2f11c5f1 100644 --- a/templates/wgsReport.html +++ b/templates/wgsReport.html @@ -84,7 +84,7 @@
{{report_data['titles'][plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#} {# jumbotron_content #} {# jumbrotron #} From 1efad706b7c147dd45601111d697534fa993c007 Mon Sep 17 00:00:00 2001 From: Cole Lyman Date: Mon, 3 Oct 2022 15:21:07 -0600 Subject: [PATCH 22/33] Replace tabs with spaces and reindent template files --- templates/layout.html | 442 ++++++------ templates/multiReport.html | 456 ++++++------ templates/report.html | 1348 ++++++++++++++++++------------------ 3 files changed, 1123 insertions(+), 1123 deletions(-) diff --git a/templates/layout.html b/templates/layout.html index 1e37522a..16551f22 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -1,237 +1,237 @@ - - CRISPResso2 - - - - - - - - - - - - - - - - - - - - - - - {% if current_user is defined %} - - {% else %} - - {% endif %} - - - - - {% block head %}{% endblock %} - - - - - {% if current_user is defined %} -
- {{ self.help_block() }} -
- - {% with messages = get_flashed_messages(with_categories=true) %} - {% if messages %} - {% for category, message in messages %} - {% if category == "error" %} - - {% else %} - - {% endif %} - {% endfor %} - {% endif %} - {% endwith %} - {% endif %} - - {# if default user (normal crispresso mode) #} - {% if current_user == null or not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} - -
-
-
- {% if current_user is defined %} -
- {% else %} -
- {% endif %} -
-
-

CRISPResso2

-

Analysis of genome editing outcomes from deep sequencing data

-
-
-
-
- - - {% else %} - {# if doing user sessions #} - +
+ {% endif %} + +
+
+
+
+ {% block help_block %} {% endblock %} +
+
+
+
+ + {% block content %}{% endblock %} + + {% if current_user is defined and (not current_user.is_anonymous and current_user.username == "DEFAULTUSER") %} +
+
+ -
-
- {% else %} -
-
- -
-
- {% endif %} + Clement K, Rees H, Canver MC, Gehrke JM, Farouni R, Hsu JY, Cole MA, Liu DR, Joung JK, Bauer DE, Pinello L.
+ CRISPResso2 provides accurate and rapid genome editing sequence analysis.
+ Nat Biotechnol. 2019 Mar; 37(3):224-226. doi: 10.1038/s41587-019-0032-3. PubMed PMID: 30809026. +

+

© Copyright Kendell Clement and Luca Pinello

+

+ + + +

+ + +
+
+ {% else %} +
+
+ +
+
+ {% endif %}
- - - - - {% block foot %}{% endblock %} - + + + + + {% block foot %}{% endblock %} + diff --git a/templates/multiReport.html b/templates/multiReport.html index 44d66112..5def61f1 100644 --- a/templates/multiReport.html +++ b/templates/multiReport.html @@ -1,44 +1,44 @@ {% extends "layout.html" %} {% block head %} {% endblock %} @@ -47,213 +47,213 @@
-
-
+
+
- {% if run_names|length > 0 %} -
-
-
{{report_name}}
-
-
-
- {% for run_name in run_names %} - {{run_name}} - {% endfor %} -
-
-
- {% endif %} + {% if run_names|length > 0 %} +
+
+
{{report_name}}
+
+
+
+ {% for run_name in run_names %} + {{run_name}} + {% endfor %} +
+
+
+ {% endif %} - {% if window_nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages around guides
-
-
- {% for plot_name in window_nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} + {% if window_nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages around guides
+
+
+ {% for plot_name in window_nuc_pct_quilts %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} - {% if nuc_pct_quilts|length > 0 %} -
-
-
Nucleotide percentages in the entire amplicon
-
-
- {% for plot_name in nuc_pct_quilts %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} + {% if nuc_pct_quilts|length > 0 %} +
+
+
Nucleotide percentages in the entire amplicon
+
+
+ {% for plot_name in nuc_pct_quilts %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} - {% if window_nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases around guides
-
-
- {% for plot_name in window_nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} + {% if window_nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases around guides
+
+
+ {% for plot_name in window_nuc_conv_plots %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} - {% if nuc_conv_plots|length > 0 %} -
-
-
Conversion of target bases in the entire amplicon
-
-
- {% for plot_name in nuc_conv_plots %} -
{{report_data['titles'][plot_name]}}
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} - {% endfor %} -
-
- {% endif %} + {% if nuc_conv_plots|length > 0 %} +
+
+
Conversion of target bases in the entire amplicon
+
+
+ {% for plot_name in nuc_conv_plots %} +
{{report_data['titles'][plot_name]}}
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} + {% endfor %} +
+
+ {% endif %} + + {% if report_data['names']|length > 0 %} + {% for plot_name in report_data['names'] %} +
+
+
{{report_data['titles'][plot_name]}}
+
+
+ {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} +
+
+ {% endfor %} + {% endif %} - {% if report_data['names']|length > 0 %} - {% for plot_name in report_data['names'] %} -
-
-
{{report_data['titles'][plot_name]}}
-
-
- {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} -
+ {% if allele_modification_heatmap_plot_names|length > 0 %} + {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} + {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} + {% set modification_type = heatmap_plot_name.split('_')[3] %} +
+
+
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
+ +
+
+
+
+ {{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} + + {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} +

Data: {{data_label}}

+ {% endfor %}
- {% endfor %} - {% endif %} +
+ {{allele_modification_line_plot_htmls[line_plot_name]}} + + {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} +

Data: {{data_label}}

+ {% endfor %} +
+
+
+
+ + {% endfor %} + + + + {% endif %} - {% if allele_modification_heatmap_plot_names|length > 0 %} - {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} - {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} - {% set modification_type = heatmap_plot_name.split('_')[3] %} -
-
-
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
- -
-
-
-
- {{allele_modification_heatmap_plot_htmls[heatmap_plot_name]}} - - {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
-
- {{allele_modification_line_plot_htmls[line_plot_name]}} - - {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} -

Data: {{data_label}}

- {% endfor %} -
-
-
-
- + {% if compact_plots_to_show|length > 0 %} +
+
+
Summary Plots
+
+
+
+ {% for compact_plot in compact_plots_to_show %} + {% endfor %} - - - - {% endif %} - - {% if compact_plots_to_show|length > 0 %} -
-
-
Summary Plots
-
-
-
- {% for compact_plot in compact_plots_to_show %} - - {% endfor %} -
-
-
- {% endif %} +
+
+
+ {% endif %} -
+
-
+
-
{# jumbotron_content #} +
{# jumbotron_content #}
{# jumbrotron #} {# column #} diff --git a/templates/report.html b/templates/report.html index a653e241..3b998cec 100644 --- a/templates/report.html +++ b/templates/report.html @@ -1,51 +1,51 @@ {% extends "layout.html" %} {% block head %} {% endblock %} @@ -53,540 +53,540 @@ {% block content %}
-
-
-
-
- {% if report_data['report_display_name'] != '' %} -
{{report_data['report_display_name']}}
- {% endif %} -
CRISPResso2 run information
- -
-
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1a', width='40%')}} -
- {{ render_partial('shared/partials/log_params.html', report_data=report_data) }} -
-
-
- -
-
-
Allele assignments
- -
-
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1b', width='40%')}} -
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1c', width='40%')}} -
- {% if report_data['figures']['locs']['plot_1d'] %} -
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1d', width='40%')}} -
- {% endif %} -
-
-
{# end card #} - - {# start global coding sequence report #} - {% if report_data['figures']['locs']['plot_5a'] %} -
-
-
Global frameshift analysis
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5a', width='40%')}} -
-
- {% endif %} - - {% if report_data['figures']['locs']['plot_6a'] %} -
-
-
Global frameshift mutagenesis profiles
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6a', width='40%')}} -
-
- {% endif %} - - {% if report_data['figures']['locs']['plot_8a'] %} -
-
-
Global splicing analysis
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a', width='40%')}} -
-
- {% endif %} - {# end of global coding sequence analysis #} - - {# start hdr summary #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
HDR summary plot
- {% else %} -
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', width='40%', amplicon_name=report_data.amplicons[0])}} -
-
- {% endif %} - {# end HDR summary #} - - {# start prime editing report #} - {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing report
- {% else %} -
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', width='40%', amplicon_name=report_data.amplicons[0])}} -
-
- {% endif %} - - {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} -
-
- {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} -
Prime editing summary plots at analysis positions
- {% else %} -
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
- {% endif %} -
-
- {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} -
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='40%', amplicon_name=report_data.amplicons[0])}} -
- {% endfor %} -
-
- {% endif %} - {# end plot 11b for prime editing #} - - {% if report_data['figures']['locs']['plot_11c'] %} -
-
-
Scaffold insertions
-
-
- {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c', width='40%')}} -
-
- {% endif %} - {# end prime editing section #} - - {% if report_data.amplicons|length == 1 %} -
{# if only one amplicon, just a normal div #} - {% else %} - {# If there is more than one amplicon, print a navigation to show each amplicon #} -

Reads are aligned to each amplicon sequence separately. Quantification and visualization of these reads are shown for each amplicon below:

-
-
-
Amplicons
- -
- {% endif %} {# end if report contains more than one amplicon #} - - - {% if report_data.amplicons|length == 1 %} {# if only one amplicon, just a normal div #} -
- {% else %} - {# jumbotron_content #} -
{# jumbrotron #} -
{# column #} +
+
+
+
+ {% if report_data['report_display_name'] != '' %} +
{{report_data['report_display_name']}}
+ {% endif %} +
CRISPResso2 run information
+ +
+
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1a', width='40%')}} +
+ {{ render_partial('shared/partials/log_params.html', report_data=report_data) }} +
+
+
+ +
+
+
Allele assignments
+ +
+
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1b', width='40%')}} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1c', width='40%')}} +
+ {% if report_data['figures']['locs']['plot_1d'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_1d', width='40%')}} +
+ {% endif %} +
+
+
{# end card #} + + {# start global coding sequence report #} + {% if report_data['figures']['locs']['plot_5a'] %} +
+
+
Global frameshift analysis
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_5a', width='40%')}} +
+
+ {% endif %} + + {% if report_data['figures']['locs']['plot_6a'] %} +
+
+
Global frameshift mutagenesis profiles
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_6a', width='40%')}} +
+
+ {% endif %} + + {% if report_data['figures']['locs']['plot_8a'] %} +
+
+
Global splicing analysis
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_8a', width='40%')}} +
+
+ {% endif %} + {# end of global coding sequence analysis #} + + {# start hdr summary #} + {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_4g'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
HDR summary plot
+ {% else %} +
HDR summary report (all reads aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_4g', width='40%', amplicon_name=report_data.amplicons[0])}} +
+
+ {% endif %} + {# end HDR summary #} + + {# start prime editing report #} + {% if report_data['figures']['locs'][report_data.amplicons[0]]['plot_11a'] %} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
Prime editing report
+ {% else %} +
Prime editing report (all reads aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11a', width='40%', amplicon_name=report_data.amplicons[0])}} +
+
+ {% endif %} + + {% if report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]] and report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b']%} +
+
+ {% if report_data.amplicons|length == 1 %} {# if only one amplicon #} +
Prime editing summary plots at analysis positions
+ {% else %} +
Prime editing summary plots at analysis positions (aligned to {{report_data.amplicons[0]}})
+ {% endif %} +
+
+ {% for fig_name in report_data['figures']['sgRNA_based_names'][report_data.amplicons[0]]['11b'] %} +
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name=fig_name, width='40%', amplicon_name=report_data.amplicons[0])}} +
+ {% endfor %} +
+
+ {% endif %} + {# end plot 11b for prime editing #} + + {% if report_data['figures']['locs']['plot_11c'] %} +
+
+
Scaffold insertions
+
+
+ {{ render_partial('shared/partials/fig_reports.html', report_data=report_data, fig_name='plot_11c', width='40%')}} +
+
+ {% endif %} + {# end prime editing section #} + + {% if report_data.amplicons|length == 1 %} +
{# if only one amplicon, just a normal div #} + {% else %} + {# If there is more than one amplicon, print a navigation to show each amplicon #} +

Reads are aligned to each amplicon sequence separately. Quantification and visualization of these reads are shown for each amplicon below:

+
+
+
Amplicons
+ +
+ {% endif %} {# end if report contains more than one amplicon #} + + + {% if report_data.amplicons|length == 1 %} {# if only one amplicon, just a normal div #} +
+ {% else %} + {# jumbotron_content #} +
{# jumbrotron #} +
{# column #}
@@ -594,100 +594,100 @@
Base editing for {{amplicon_name}}
{% block foot %} + function updateZoom(e) { + /*prevent any other actions that may occur when moving over the image:*/ + // e.preventDefault(); + var img = e.target.imgObj + var view = e.target.viewObj + var lens = e.target.lensObj + + if (!lens.hasWidthSet) + { + view_height = $('#'+view.id).height() + view_width = $('#'+view.id).width() + img_height = $('#'+img.id).height() + img_width = $('#'+img.id).width() + lens_height = $('#'+lens.id).height() + lens_width = $('#'+lens.id).width() + + new_width = img_height * view_width/view_height //make up for loss of precision + $('#'+lens.id).outerWidth(new_width) + lens.hasWidthSet = true + + cx = view_width / new_width + + view.view_height = view_height + view.view_width = view_width + img.img_height = img_height + img.img_width = img_width + lens.lens_height = lens_height + lens.lens_width = new_width + + } + + var pos, x, y; + /*get the cursor's x and y positions:*/ + pos = getCursorPos(e,img); + /*calculate the position of the lens:*/ + x = pos.x - (lens.lens_width / 2); + /*prevent the lens from being positioned outside the image:*/ + if (x > img.img_width - lens.lens_width) {x = img.img_width - lens.lens_width;; + } + if (x < 0) {x = 0;} + lens.style.left = x + "px"; + view.style.backgroundPosition = "-" + (x * cx) + "px 0px"; + } + + function getCursorPos(e,img) { + var a, x = 0, y = 0; + e = e || window.event; + /*get the x and y positions of the image:*/ + a = img.getBoundingClientRect(); + /*calculate the cursor's x and y coordinates, relative to the image:*/ + x = e.pageX - a.left; + y = e.pageY - a.top; + /*consider any page scrolling:*/ + x = x - window.pageXOffset; + y = y - window.pageYOffset; + return {x : x, y : y}; + } + + var passiveSupported = false; + try { + var options = { + get passive() { // This function will be called when the browser + // attempts to access the passive property. + passiveSupported = true; + } + }; + + window.addEventListener("test", options, options); + window.removeEventListener("test", options, options); + } catch(err) { + passiveSupported = false; + } + + {% for amplicon_name in report_data.amplicons %} + {% if report_data['figures']['locs'][amplicon_name]['plot_2a'] %} + view = document.getElementById('zoomview_nucs_{{amplicon_name}}'); + img = document.getElementById('tozoom_nucs_{{amplicon_name}}'); + lens = document.getElementById('zoomlens_nucs_{{amplicon_name}}') + + img.viewObj = view + img.lensObj = lens + img.imgObj = img + + lens.viewObj = view + lens.lensObj = lens + lens.imgObj = img + + lens.addEventListener("mousemove", updateZoom, passiveSupported? { passive: true } : false); + img.addEventListener("mousemove", updateZoom, passiveSupported? { passive: true } : false); + /*and also for touch screens:*/ + lens.addEventListener("touchmove", updateZoom, passiveSupported? { passive: true } : false); + img.addEventListener("touchmove", updateZoom, passiveSupported? { passive: true } : false); + + {% endif %} + {% endfor %} + {% endblock %} From e80a13932ef1651db312ee4d0cf31290dbc8df6f Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Tue, 4 Oct 2022 10:36:52 -0600 Subject: [PATCH 23/33] Indentation and parenthesis --- templates/batchReport.html | 2 +- templates/layout.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/batchReport.html b/templates/batchReport.html index cb9d4aa0..58a41e97 100644 --- a/templates/batchReport.html +++ b/templates/batchReport.html @@ -148,7 +148,7 @@
{{report_data['titles'][plot_name]}}
{# data bit for web version: #} {# -

Data: {{data_label}}

+

Data: {{data_label}}

#} {# jumbotron_content #} {# jumbrotron #} diff --git a/templates/layout.html b/templates/layout.html index 16551f22..b74ab9bc 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -113,7 +113,7 @@ {% endif %} {# if default user (normal crispresso mode) #} - {% if current_user == null or not current_user.is_anonymous and current_user.username == "DEFAULTUSER" %} + {% if current_user == null or (not current_user.is_anonymous and current_user.username == "DEFAULTUSER") %}
From dcf739175ff8db098d63b9b000afd0bdb59e6dff Mon Sep 17 00:00:00 2001 From: Samuel Nichols Date: Mon, 6 Feb 2023 16:24:45 -0700 Subject: [PATCH 24/33] Adding styling for print-only and screen only --- templates/layout.html | 14 +++- templates/report.html | 96 ++++++++++++++--------- templates/shared/partials/log_params.html | 16 +++- 3 files changed, 86 insertions(+), 40 deletions(-) diff --git a/templates/layout.html b/templates/layout.html index dba520de..4a10539a 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -66,6 +66,16 @@ display:none } } + + @media screen + { + .print-only{ + display: none !important; + } + .screen-only{ + display: block; + } + } @@ -197,9 +207,9 @@

Analysis of genome editing ou {% if current_user is defined and (not current_user.is_anonymous and current_user.username == "DEFAULTUSER") %}
-