Commit 7e51d455 authored by Sander Bollen's avatar Sander Bollen
Browse files

create primer3 configuration from template.

parent 5560f6d0
...@@ -15,6 +15,7 @@ import json ...@@ -15,6 +15,7 @@ import json
import re import re
from jinja2 import Template
from jsonschema import validate from jsonschema import validate
from .models import Primer from .models import Primer
...@@ -22,9 +23,11 @@ from .models import Primer ...@@ -22,9 +23,11 @@ from .models import Primer
SETTINGS_SCHEMA = (Path(__file__).parent / Path("static") / SETTINGS_SCHEMA = (Path(__file__).parent / Path("static") /
Path("primer3_settings_schema.json")) Path("primer3_settings_schema.json"))
TEMPLATE = Path(__file__).parent / Path("static") / Path("primer3_conf.j2")
def parse_settings(settings_file: Optional[Path] = None) -> dict: def parse_settings(settings_file: Optional[Path] = None,
settings_schema: Path = SETTINGS_SCHEMA) -> dict:
""" """
Parse settings file to settings dictionary. Parse settings file to settings dictionary.
...@@ -32,10 +35,12 @@ def parse_settings(settings_file: Optional[Path] = None) -> dict: ...@@ -32,10 +35,12 @@ def parse_settings(settings_file: Optional[Path] = None) -> dict:
in schema. If settings_file is None, all values will be the default values in schema. If settings_file is None, all values will be the default values
in schema in schema
:param settings_file: Optional path to settings file :param settings_file: Optional path to settings file
:param settings_schema: Path to schema json for settings. Default is
supplied schema in static/primer3_settings_schema.json
:return: dict with settings :return: dict with settings
:raises: ValidationError if settings_file does not conform to schema :raises: ValidationError if settings_file does not conform to schema
""" """
with SETTINGS_SCHEMA.open("r") as schema_handle: with settings_schema.open("r") as schema_handle:
schema_dict = json.load(schema_handle) schema_dict = json.load(schema_handle)
defaults = {k: v['default'] for k, v in schema_dict['properties'].items()} defaults = {k: v['default'] for k, v in schema_dict['properties'].items()}
...@@ -63,6 +68,25 @@ def parse_settings(settings_file: Optional[Path] = None) -> dict: ...@@ -63,6 +68,25 @@ def parse_settings(settings_file: Optional[Path] = None) -> dict:
return generated_dict return generated_dict
def create_primer3_config(settings_dict: dict,
sequence_template: str,
sequence_target: str,
excluded_region: str,
template_path: Path = TEMPLATE) -> str:
"""Create primer3 configuration from jinja2 template and settings_dict"""
with template_path.open("r") as thandle:
template = Template(thandle.read())
return template.render(
{
"seq": sequence_template,
"target": sequence_target,
"excluded_region": excluded_region,
"settings": settings_dict
}
)
class Primer3(object): class Primer3(object):
def __init__(self, primer3_exe, template, target, excluded_region, def __init__(self, primer3_exe, template, target, excluded_region,
......
...@@ -14,7 +14,7 @@ PRIMER_INTERNAL_MAX_GC={{ settings.primer_internal_max_gc }} ...@@ -14,7 +14,7 @@ PRIMER_INTERNAL_MAX_GC={{ settings.primer_internal_max_gc }}
PRIMER_WT_GC_PERCENT_LT={{ settings.primer_wt_gc_percent_lt }} PRIMER_WT_GC_PERCENT_LT={{ settings.primer_wt_gc_percent_lt }}
PRIMER_INTERNAL_WT_GC_PERCENT_LT={{ settings.primer_internal_wt_gc_percent_lt }} PRIMER_INTERNAL_WT_GC_PERCENT_LT={{ settings.primer_internal_wt_gc_percent_lt }}
PRIMER_WT_GC_PERCENT_GT={{ settings.primer_wt_gc_percent_gt }} PRIMER_WT_GC_PERCENT_GT={{ settings.primer_wt_gc_percent_gt }}
PRIMER_INTERNAL_WT_GC_PERCENT_GT={{ settings.primer_internal_wc_gc_percent_gt }} PRIMER_INTERNAL_WT_GC_PERCENT_GT={{ settings.primer_internal_wt_gc_percent_gt }}
PRIMER_GC_CLAMP={{ settings.primer_gc_clamp }} PRIMER_GC_CLAMP={{ settings.primer_gc_clamp }}
PRIMER_MAX_END_GC={{ settings.primer_max_end_gc }} PRIMER_MAX_END_GC={{ settings.primer_max_end_gc }}
PRIMER_OPT_SIZE={{ settings.primer_opt_size }} PRIMER_OPT_SIZE={{ settings.primer_opt_size }}
......
SEQUENCE_ID=prinia_template
SEQUENCE_TEMPLATE=ACTG
SEQUENCE_TARGET=50-60
SEQUENCE_EXCLUDED_REGION=50-60
PRIMER_TASK=pick_detection_primers
PRIMER_PICK_LEFT_PRIMER=1
PRIMER_PICK_INTERNAL_OLIGO=0
PRIMER_PICK_RIGHT_PRIMER=1
PRIMER_MIN_GC=20
PRIMER_INTERNAL_MIN_GC=20
PRIMER_OPT_GC_PERCENT=50
PRIMER_MAX_GC=80
PRIMER_INTERNAL_MAX_GC=80
PRIMER_WT_GC_PERCENT_LT=0
PRIMER_INTERNAL_WT_GC_PERCENT_LT=0
PRIMER_WT_GC_PERCENT_GT=0
PRIMER_INTERNAL_WT_GC_PERCENT_GT=0
PRIMER_GC_CLAMP=0
PRIMER_MAX_END_GC=5
PRIMER_OPT_SIZE=25
PRIMER_MIN_SIZE=20
PRIMER_MAX_SIZE=30
PRIMER_MAX_NS_ACCEPTED=0
PRIMER_PRODUCT_SIZE_RANGE=200-450
PRIMER_PRODUCT_OPT_SIZE=325
PRIMER_PAIR_WT_PRODUCT_SIZE_GT=0.1
PRIMER_PAIR_WT_PRODUCT_SIZE_LT=0.1
P3_FILE_FLAG=1
SEQUENCE_INTERNAL_EXCLUDED_REGION=37,21
PRIMER_EXPLAIN_FLAG=1
PRIMER_MIN_TM=58
PRIMER_MAX_TM=62
PRIMER_NUM_RETURN=200
\ No newline at end of file
SEQUENCE_ID=prinia_template
SEQUENCE_TEMPLATE=ACTG
SEQUENCE_TARGET=50-60
SEQUENCE_EXCLUDED_REGION=50-60
PRIMER_TASK=pick_detection_primers
PRIMER_PICK_LEFT_PRIMER=1
PRIMER_PICK_INTERNAL_OLIGO=0
PRIMER_PICK_RIGHT_PRIMER=1
PRIMER_MIN_GC=30
PRIMER_INTERNAL_MIN_GC=30
PRIMER_OPT_GC_PERCENT=51
PRIMER_MAX_GC=81
PRIMER_INTERNAL_MAX_GC=81
PRIMER_WT_GC_PERCENT_LT=0.12
PRIMER_INTERNAL_WT_GC_PERCENT_LT=0.12
PRIMER_WT_GC_PERCENT_GT=0.12
PRIMER_INTERNAL_WT_GC_PERCENT_GT=0.12
PRIMER_GC_CLAMP=1
PRIMER_MAX_END_GC=0
PRIMER_OPT_SIZE=21
PRIMER_MIN_SIZE=19
PRIMER_MAX_SIZE=29
PRIMER_MAX_NS_ACCEPTED=1
PRIMER_PRODUCT_SIZE_RANGE=300-500
PRIMER_PRODUCT_OPT_SIZE=300
PRIMER_PAIR_WT_PRODUCT_SIZE_GT=0.12
PRIMER_PAIR_WT_PRODUCT_SIZE_LT=0.12
P3_FILE_FLAG=1
SEQUENCE_INTERNAL_EXCLUDED_REGION=37,21
PRIMER_EXPLAIN_FLAG=1
PRIMER_MIN_TM=55
PRIMER_MAX_TM=75
PRIMER_NUM_RETURN=100
\ No newline at end of file
SEQUENCE_ID=prinia_template
SEQUENCE_TEMPLATE=ACTG
SEQUENCE_TARGET=50-60
SEQUENCE_EXCLUDED_REGION=50-60
PRIMER_TASK=pick_detection_primers
PRIMER_PICK_LEFT_PRIMER=1
PRIMER_PICK_INTERNAL_OLIGO=0
PRIMER_PICK_RIGHT_PRIMER=1
PRIMER_MIN_GC=20
PRIMER_INTERNAL_MIN_GC=20
PRIMER_OPT_GC_PERCENT=50
PRIMER_MAX_GC=80
PRIMER_INTERNAL_MAX_GC=80
PRIMER_WT_GC_PERCENT_LT=0
PRIMER_INTERNAL_WT_GC_PERCENT_LT=0
PRIMER_WT_GC_PERCENT_GT=0
PRIMER_INTERNAL_WT_GC_PERCENT_GT=0
PRIMER_GC_CLAMP=1
PRIMER_MAX_END_GC=0
PRIMER_OPT_SIZE=21
PRIMER_MIN_SIZE=19
PRIMER_MAX_SIZE=29
PRIMER_MAX_NS_ACCEPTED=1
PRIMER_PRODUCT_SIZE_RANGE=300-500
PRIMER_PRODUCT_OPT_SIZE=400
PRIMER_PAIR_WT_PRODUCT_SIZE_GT=0.12
PRIMER_PAIR_WT_PRODUCT_SIZE_LT=0.12
P3_FILE_FLAG=1
SEQUENCE_INTERNAL_EXCLUDED_REGION=37,21
PRIMER_EXPLAIN_FLAG=1
PRIMER_MIN_TM=55
PRIMER_MAX_TM=75
PRIMER_NUM_RETURN=100
\ No newline at end of file
...@@ -7,19 +7,19 @@ test_primer3.py ...@@ -7,19 +7,19 @@ test_primer3.py
:license: MIT :license: MIT
""" """
from pathlib import Path from pathlib import Path
from pytest import fixture import pytest
from prinia.primer3 import parse_settings, create_primer3_config
from prinia.primer3 import parse_settings
data_dir = Path(__file__).parent / Path("data") data_dir = Path(__file__).parent / Path("data")
@fixture
@pytest.fixture
def valid_settings(): def valid_settings():
return data_dir / Path("valid_settings.json") return data_dir / Path("valid_settings.json")
@fixture @pytest.fixture
def valid_partial_settings(): def valid_partial_settings():
return data_dir / Path("valid_partial_settings.json") return data_dir / Path("valid_partial_settings.json")
...@@ -108,3 +108,26 @@ def test_partial_settings(valid_partial_settings): ...@@ -108,3 +108,26 @@ def test_partial_settings(valid_partial_settings):
"primer_num_return": 100 "primer_num_return": 100
} }
configuration_data = [
(None, data_dir / Path("primer3_conf_default.txt")),
(
data_dir / Path("valid_settings.json"),
data_dir / Path("primer3_conf_full_settings.txt")
),
(
data_dir / Path("valid_partial_settings.json"),
data_dir / Path("primer3_conf_partial_settings.txt")
)
]
@pytest.mark.parametrize("settings_json, conf", configuration_data)
def test_primer3_configuration(settings_json, conf):
parsed_settings = parse_settings(settings_json)
generated_conf = create_primer3_config(parsed_settings, "ACTG",
"50-60", "50-60")
with conf.open("r") as chandle:
expected_conf = chandle.read().strip()
assert generated_conf == expected_conf
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment