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
import re
from jinja2 import Template
from jsonschema import validate
from .models import Primer
......@@ -22,9 +23,11 @@ from .models import Primer
SETTINGS_SCHEMA = (Path(__file__).parent / Path("static") /
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.
......@@ -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
: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
: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)
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:
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):
def __init__(self, primer3_exe, template, target, excluded_region,
......
......@@ -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_INTERNAL_WT_GC_PERCENT_LT={{ settings.primer_internal_wt_gc_percent_lt }}
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_MAX_END_GC={{ settings.primer_max_end_gc }}
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
:license: MIT
"""
from pathlib import Path
from pytest import fixture
from prinia.primer3 import parse_settings
import pytest
from prinia.primer3 import parse_settings, create_primer3_config
data_dir = Path(__file__).parent / Path("data")
@fixture
@pytest.fixture
def valid_settings():
return data_dir / Path("valid_settings.json")
@fixture
@pytest.fixture
def valid_partial_settings():
return data_dir / Path("valid_partial_settings.json")
......@@ -108,3 +108,26 @@ def test_partial_settings(valid_partial_settings):
"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