Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mckay/c2pro reports test #99

Merged
merged 9 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ jobs:
uses: actions/checkout@v3
with:
repository: edilytics/CRISPResso2_tests
ref: 'mckay/c2pro-tests'
# ref: '<BRANCH-NAME>' # update to specific branch

- name: Run Basic
Expand Down
2 changes: 2 additions & 0 deletions CRISPResso2/CRISPRessoReports/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.html text eol=lf
*.md text eol=lf
93 changes: 54 additions & 39 deletions CRISPResso2/CRISPRessoReports/CRISPRessoReport.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,30 @@
from CRISPResso2 import CRISPRessoShared

if CRISPRessoShared.is_C2Pro_installed():
from CRISPRessoPro import __version__ as CRISPRessoProVersion
import CRISPRessoPro
C2PRO_INSTALLED = True
else:
C2PRO_INSTALLED = False


def get_jinja_loader(root, logger):
UndefinedLogger = make_logging_undefined(logger=logger)
"""
Get the Jinja2 environment for rendering templates.
"""
undefined_logger = make_logging_undefined(logger=logger)
if C2PRO_INSTALLED:
return Environment(
loader=ChoiceLoader([
FileSystemLoader(os.path.join(root, 'CRISPRessoReports', 'templates')),
FileSystemLoader(os.path.join(os.path.dirname(CRISPRessoPro.__file__), 'templates')),
]),
undefined=UndefinedLogger,
)
else:
return Environment(
loader=FileSystemLoader(os.path.join(root, 'CRISPRessoReports', 'templates')),
undefined=UndefinedLogger,
undefined=undefined_logger,
)
return Environment(
loader=FileSystemLoader(os.path.join(root, 'CRISPRessoReports', 'templates')),
undefined=undefined_logger,
)


def render_template(template_name, jinja2_env, **data):
Expand Down Expand Up @@ -67,20 +70,20 @@ def custom_partial_render(partial_template_name, **partial_data):
)


def make_report_from_folder(crispresso_report_file, crispresso_folder, _ROOT):
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)
_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)
make_report(run_data, crispresso_report_file, crispresso_folder, _root)


def add_fig_if_exists(fig, fig_name, fig_root, fig_title, fig_caption, fig_data,
Expand All @@ -106,15 +109,15 @@ def add_fig_if_exists(fig, fig_name, fig_root, fig_title, fig_caption, 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, encoding="utf-8") as html:
with open(htmlfullpath, encoding='utf-8') as html:
html_string = "<div align='center'>"
html_string += html.read()
html_string += "</div>"
amplicon_figures['htmls'][fig_name] = html_string
elif os.path.exists(jsonfullpath) and C2PRO_INSTALLED:
root_name = fig_root.replace('.', '_').replace('-', '_')
d3_nuc_quilt_names.append(f"nuc_quilt_{root_name}")
with open(jsonfullpath) as fig_json_fh:
with open(jsonfullpath, encoding='utf-8') as fig_json_fh:
amplicon_figures['htmls'][fig_name] = f"""
<div class="d-flex justify-content-between" style="max-height: 80vh; overflow-y: auto;" id="{f"nuc_quilt_{root_name}"}"></div>
<script type="text/javascript">const {f"nuc_quilt_{root_name}"} = {fig_json_fh.read().strip()}</script>
Expand Down Expand Up @@ -177,10 +180,10 @@ def assemble_figs(run_data, crispresso_folder):
return data


def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, logger):
# 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)
def make_report(run_data, crispresso_report_file, crispresso_folder, _root, logger):
"""
Writes an HMTL report for a CRISPResso run
"""
data = assemble_figs(run_data, crispresso_folder)

report_display_name = ""
Expand All @@ -203,19 +206,22 @@ def make_report(run_data, crispresso_report_file, crispresso_folder, _ROOT, logg
'nuc_quilt_names': data['nuc_quilt_names'],
}

j2_env = get_jinja_loader(_ROOT, logger)
j2_env = get_jinja_loader(_root, logger)

# 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)
# 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', encoding="utf-8") as outfile:
outfile.write(render_template(
'report.html', j2_env, report_data=report_data, C2PRO_INSTALLED=C2PRO_INSTALLED,
))


def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info, batch_folder, _ROOT, logger):
def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info, batch_folder, _root, logger):
"""
Makes a report for a CRIPSRessoBatch run
"""
batch_names = crispresso2_info['results']['completed_batch_arr']
failed_runs = crispresso2_info['results']['failed_batch_arr']
failed_runs_desc = crispresso2_info['results']['failed_batch_arr_desc']
Expand Down Expand Up @@ -305,7 +311,7 @@ def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info,
summary_plot_htmls = {}
for plot_name in window_nuc_pct_quilts + nuc_pct_quilts:
if os.path.exists(os.path.join(batch_folder, f'{plot_name}.json')):
with open(os.path.join(batch_folder, f'{plot_name}.json')) as window_nuc_pct_json_fh:
with open(os.path.join(batch_folder, f'{plot_name}.json'), encoding='utf-8') as window_nuc_pct_json_fh:
summary_plot_htmls[plot_name] = f"""
<div class="d-flex justify-content-between" style="max-height: 80vh; overflow-y: auto;" id="{plot_name}"></div>
<script type="text/javascript">const {plot_name} = {window_nuc_pct_json_fh.read().strip()}</script>
Expand Down Expand Up @@ -346,7 +352,7 @@ def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info,
sub_html_files,
crispressoBatch_report_file,
batch_folder,
_ROOT,
_root,
output_title,
'batch',
logger,
Expand All @@ -366,41 +372,50 @@ def make_batch_report_from_folder(crispressoBatch_report_file, crispresso2_info,
)


def make_pooled_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT, logger):
def make_pooled_report_from_folder(crispresso_report_file, crispresso2_info, folder, _root, logger):
"""
Makes a report for a CRISPRessoPooled run
"""
names_arr = crispresso2_info['results']['good_region_names']
output_title = 'CRISPResso Pooled Output'
if crispresso2_info['running_info']['args'].name != '':
output_title += f"<br/>{crispresso2_info['running_info']['args'].name}"
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'pooled', logger)
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _root, 'pooled', logger)


def make_compare_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT, logger):
def make_compare_report_from_folder(crispresso_report_file, crispresso2_info, folder, _root, logger):
"""
Makes a report for a CRISPRessoCompare run
"""
names_arr = []
output_title = 'CRISPResso Compare Output'
if crispresso2_info['running_info']['args'].name != '':
output_title += "<br/>{crispresso2_info['running_info']['args'].name}"
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'compare', logger)
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _root, 'compare', logger)


def make_meta_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT, logger):
def make_meta_report_from_folder(crispresso_report_file, crispresso2_info, folder, _root, logger):
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 += "<br/>{crispresso2_info['running_info']['args'].name}"
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'meta', logger,
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _root, 'meta', logger,
display_names=input_names)


def make_wgs_report_from_folder(crispresso_report_file, crispresso2_info, folder, _ROOT, logger):
def make_wgs_report_from_folder(crispresso_report_file, crispresso2_info, folder, _root, logger):
"""
Makes a report for a CRISPRessoWGS run
"""
names_arr = crispresso2_info['results']['good_region_names']
output_title = 'CRISPResso WGS Output'
if crispresso2_info['running_info']['args'].name != '':
output_title += "<br/>{crispresso2_info['running_info']['args'].name}"
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _ROOT, 'wgs', logger)
make_multi_report_from_folder(crispresso2_info, names_arr, output_title, crispresso_report_file, folder, _root, 'wgs', logger)


def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, crispresso_report_file, folder, _ROOT, crispresso_tool, logger,
def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, crispresso_report_file, folder, _root, crispresso_tool, logger,
display_names=None):
"""
Prepares information to make a report of multiple CRISPResso runs - like CRISPRessoWGS or CRISPRessoPooled
Expand All @@ -411,7 +426,7 @@ def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, cris
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)
_root (string): location of crispresso assets (images, templates, etc)
logger (logging.Logger): logger to log messages to, mainly for undefined variables in Jinja2 templates
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)
Expand Down Expand Up @@ -483,7 +498,7 @@ def make_multi_report_from_folder(crispresso2_info, names_arr, report_name, cris
sub_html_files,
crispresso_report_file,
folder,
_ROOT,
_root,
report_name,
crispresso_tool,
logger,
Expand All @@ -503,7 +518,7 @@ def make_multi_report(
sub_html_files,
crispresso_multi_report_file,
crispresso_folder,
_ROOT,
_root,
report_name,
crispresso_tool,
logger,
Expand All @@ -525,7 +540,7 @@ def make_multi_report(
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
_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
Expand All @@ -547,7 +562,7 @@ def fill_default(dictionary, key, default_type=list):
if key not in dictionary:
dictionary[key] = default_type()

j2_env = get_jinja_loader(_ROOT, logger)
j2_env = get_jinja_loader(_root, logger)

j2_env.filters['dirname'] = dirname
if crispresso_tool == 'batch':
Expand Down Expand Up @@ -643,7 +658,7 @@ def make_aggregate_report(
report_name,
crispresso_report_file,
crispresso_report_folder,
_ROOT,
_root,
folder_arr,
crispresso_html_reports,
logger,
Expand All @@ -658,7 +673,7 @@ def make_aggregate_report(
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)
_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
logger (logging.Logger): logger to log messages
Expand Down Expand Up @@ -778,7 +793,7 @@ def make_aggregate_report(
sub_html_files,
crispresso_report_file,
crispresso_report_folder,
_ROOT,
_root,
report_name,
'aggregate',
logger,
Expand Down
4 changes: 2 additions & 2 deletions CRISPResso2/CRISPRessoReports/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Take care when committing into these files as not to mix unrelated git histories

## How do I work with this repo?

Step 1 only needs to be done once per cloned repo, the other steps will need to be dne more frequently.
Step 1 only needs to be done once per cloned repo, the other steps will need to be done more frequently.

1. Add the remote to this repo to the "parent" repo (i.e. `CRISPResso2` or `C2Web`). **You should only have to do this once.**

Expand Down Expand Up @@ -131,7 +131,7 @@ If a feature that you are working on requires changes to CRISPRessoReports, you
1. Create a feature branch in the parent repo, based on the parent repo master.

``` shell
git checkout -b <feature-branch>
git checkout -b <feature-branch> origin/master
```

2. Create a feature branch on `CRISPRessoReports`.
Expand Down
6 changes: 6 additions & 0 deletions CRISPResso2/CRISPRessoReports/jinja_partials.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@


def render_partial(template_name, renderer=None, markup=True, **data):
"""
Renders a partial template and returns the result. If `markup` is True, the result is wrapped in a `Markup` object.
"""
if renderer is None:
if flask is None:
raise PartialsException('No renderer specified')
Expand All @@ -43,4 +46,7 @@ def render_partial(template_name, renderer=None, markup=True, **data):


def generate_render_partial(renderer, markup=True):
"""
Returns a partial function that renders a template using the specified renderer.
"""
return partial(render_partial, renderer=renderer, markup=markup)
Loading
Loading