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

feat(#741): Pretty print #742

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c254b47
feat(pretty print): adding some experimental code for pretty printing…
andreasprlic May 13, 2024
8986d20
feat(pretty print): making sure we don't bloat the test cache.
andreasprlic May 13, 2024
e9fde79
feat(pretty print): making type py3.8 compatible
andreasprlic May 13, 2024
d3a5e6e
feat(pretty print): breaking up creation of each line in display into…
andreasprlic May 28, 2024
f2018df
feat(pretty print): breaking up creation of each line in display into…
andreasprlic May 29, 2024
2f7069b
feat(pretty print): feat(pretty print): improvements for RNA coding t…
andreasprlic Jun 1, 2024
27ae2cd
feat(repeat-detection): using fully justified representation.
andreasprlic Jun 3, 2024
b5b3d64
feat(repeat-detection): using fully justified representation.
andreasprlic Jun 3, 2024
2a72299
formatting
andreasprlic Jun 3, 2024
0dcab28
feat(prot-pos): now showing the protein (amino acid) positions more c…
andreasprlic Jun 6, 2024
e9f578a
feat(repeat-detection): now with better detection of repetitive units…
andreasprlic Jun 7, 2024
99a614f
feat(repeat-detection): hooking repeat detection improvements in pret…
andreasprlic Jun 7, 2024
da48e01
Merge branch 'main' into pretty_print
andreasprlic Jun 9, 2024
f1e9703
feat(pretty_print): now showing hgvs_p, making code more accessible f…
andreasprlic Jun 30, 2024
7ad7f0c
Merge branch 'main' of github.com:biocommons/hgvs into pretty_print
andreasprlic Jun 30, 2024
a31cd26
feat(ci): trying to get pytest to work again
andreasprlic Jun 30, 2024
30addf2
feat(cleanup): removing cache from test_repeats. They are creating to…
andreasprlic Jul 1, 2024
bc483b5
cleanup
andreasprlic Aug 13, 2024
cf22aae
#741 small refactoring to update directory structure, based on PR com…
andreasprlic Sep 2, 2024
d4f2ac4
Merge branch 'main' into pretty_print
andreasprlic Sep 2, 2024
d08f02d
#741 small refactoring to update directory structure, based on PR com…
andreasprlic Sep 2, 2024
401c5a3
#741 excluding data intensive tests from CI. They would create too mu…
andreasprlic Sep 6, 2024
336ea2c
trying to fix CI
andreasprlic Sep 6, 2024
d216bba
feat(repeats): found an issue with count_pattern_occurences, fixed an…
andreasprlic Sep 7, 2024
9d15a22
feat(repeats): adding examples from HGVS repeats recommendations page…
andreasprlic Sep 16, 2024
99f27bf
feat(repeats): adding an example of a large variant to make sure we d…
andreasprlic Sep 17, 2024
703efbf
feat(repeats): moving max repeat config to global config. Also a smal…
andreasprlic Sep 19, 2024
bb7eb3c
skipfeat(repeats): skipping more tests that are too data heavy.
andreasprlic Sep 19, 2024
fed5af4
feat(repeats): improvements in repeat check.
andreasprlic Sep 19, 2024
9a2e049
feat(reverse-strand): Now showing reverse strand transcript in 5'-3' …
andreasprlic Oct 3, 2024
b82ab35
feat(is_rna): moving the check if a transcript is RNA only to datacom…
andreasprlic Oct 3, 2024
cdd87a5
fix
andreasprlic Oct 3, 2024
9a77892
fixing off-by one error at transcript start, problematic intergenic v…
andreasprlic Nov 16, 2024
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
4 changes: 3 additions & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ jobs:

- name: Install dependencies
run: |
pip install -e .[dev]
pip install setuptools
pip install -e .[dev]
pip install pytest pytest-cov

- name: Test with pytest
run: |
Expand Down
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ keywords = [
"hgvs",
"variation"
]
dynamic = ["version", "optional-dependencies"]
dynamic = ["version"]

dependencies=[
"attrs >= 17.4.0", # https://github.com/biocommons/hgvs/issues/473
Expand All @@ -45,6 +45,11 @@ dependencies=[
"six",
]

[project.optional-dependencies]
dev = [
"parameterized"
]

[project.urls]
"Homepage" = "https://github.com/biocommons/hgvs"
"Bug Tracker" = "https://github.com/biocommons/hgvs/issues"
Expand Down
2 changes: 2 additions & 0 deletions src/hgvs/easy.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from hgvs.dataproviders.uta import connect
from hgvs.normalizer import Normalizer
from hgvs.parser import Parser
from hgvs.pretty.pretty_print import PrettyPrint
from hgvs.validator import Validator
from hgvs.variantmapper import VariantMapper

Expand Down Expand Up @@ -66,6 +67,7 @@
t_to_g = projector.t_to_g
t_to_p = projector.t_to_p
get_relevant_transcripts = am38.relevant_transcripts
pretty = PrettyPrint(hdp, useColor=True, showLegend=True)

# <LICENSE>
# Copyright 2018 HGVS Contributors (https://github.com/biocommons/hgvs)
Expand Down
2 changes: 1 addition & 1 deletion src/hgvs/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def __init__(self, grammar_fn=None, expose_all_rules=False):
self._logger = logging.getLogger(__name__)
self._expose_rule_functions(expose_all_rules)

def parse(self, v):
def parse(self, v) -> hgvs.sequencevariant.SequenceVariant:
"""parse HGVS variant `v`, returning a SequenceVariant

:param str v: an HGVS-formatted variant as a string
Expand Down
37 changes: 37 additions & 0 deletions src/hgvs/pretty/console/chrom_seq_renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from hgvs.pretty.models import VariantData
from hgvs.pretty.console.renderer import BasicRenderer


class ChromSeqRendered(BasicRenderer):

def legend(self) -> str:
return "seq -> : "

def display(self, data: VariantData) -> str:
"""colors the ref sequences with adenine (A, green), thymine (T, red), cytosine (C, yellow), and guanine (G, blue)"""
from hgvs.pretty.console.constants import ENDC, TBLUE, TGREEN, TRED, TYELLOW

var_seq = ""
for p in data.position_details:
c = p.ref

if not c:
var_seq += "."
continue

if self.config.useColor:
if c == "A":
var_seq += TGREEN
elif c == "T":
var_seq += TRED
elif c == "C":
var_seq += TYELLOW
elif c == "G":
var_seq += TBLUE

var_seq += c

if self.config.useColor:
var_seq += ENDC

return var_seq
39 changes: 39 additions & 0 deletions src/hgvs/pretty/console/chrom_seq_reverse_renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from bioutils.sequences import reverse_complement

from hgvs.pretty.models import VariantData
from hgvs.pretty.console.renderer import BasicRenderer


class ChromReverseSeqRendered(BasicRenderer):

def legend(self) -> str:
return "seq <- : "

def display(self, data: VariantData) -> str:
"""colors the ref sequences with adenine (A, green), thymine (T, red), cytosine (C, yellow), and guanine (G, blue)"""
from hgvs.pretty.console.constants import ENDC, TBLUE, TGREEN, TRED, TYELLOW

var_seq = ""
for p in data.position_details:
c = reverse_complement(p.ref)

if not c:
var_seq += "."
continue

if self.config.useColor:
if c == "A":
var_seq += TGREEN
elif c == "T":
var_seq += TRED
elif c == "C":
var_seq += TYELLOW
elif c == "G":
var_seq += TBLUE

var_seq += c

if self.config.useColor:
var_seq += ENDC

return var_seq
14 changes: 14 additions & 0 deletions src/hgvs/pretty/console/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
### Color constants for rendering text on the console

TGREEN = "\033[32m" # Green Text
TGREENBG = "\033[30;42m"
TRED = "\033[31m" # Red Text
TREDBG = "\033[30;41m"
TBLUE = "\033[34m" # Blue Text
TBLUEBG = "\033[30;44m"
TPURPLE = "\033[35m" # Purple Text
TPURPLEBG = "\033[30;45m"
TYELLOW = "\033[33m" # Yellow Text
TYELLOWBG = "\033[30;43m"

ENDC = "\033[m" # reset to the defaults
33 changes: 33 additions & 0 deletions src/hgvs/pretty/console/pos_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from hgvs.pretty.models import VariantData
from hgvs.pretty.console.renderer import BasicRenderer


class ChrPositionInfo(BasicRenderer):

def legend(self):
return " : "

def display(self, data: VariantData) -> str:

count = -1
var_seq = ""
for pdata in data.position_details:
count += 1
g = pdata.chromosome_pos

total_chars = len(var_seq)

if total_chars > count:
continue

if not g:
var_seq += " "
continue

if g % 10 == 0:
var_seq += f"{g:,} "

else:
var_seq += " "

return var_seq.rstrip()
43 changes: 43 additions & 0 deletions src/hgvs/pretty/console/prot_mapping_renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from hgvs.pretty.models import VariantData
from hgvs.pretty.console.renderer import BasicRenderer


class ProtMappingRenderer(BasicRenderer):
"""Prints the position in p (amino acid) coordinates."""

def legend(self):
return "aa pos : "

def display(self, data: VariantData) -> str:
"""show the position of the transcript seq"""

var_str = ""

count = -1
for pdata in data.position_details:
count += 1
if not pdata.mapped_pos:
var_str += " "
continue

prot_data = pdata.protein_data

if not prot_data or prot_data.aa_pos < 0:
var_str += " "
continue

if len(var_str) > count:
continue

aa_pos = prot_data.aa_pos
if (aa_pos + 1) % 10 == 0:
var_str += "|"
continue

elif (aa_pos + 1) % 5 == 0:
var_str += "."
continue

var_str += " "

return var_str
52 changes: 52 additions & 0 deletions src/hgvs/pretty/console/prot_ruler_renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from hgvs.pretty.models import VariantData
from hgvs.pretty.console.renderer import BasicRenderer


class ProtRulerRenderer(BasicRenderer):

def legend(self) -> str:
return " : "

def display(self, data: VariantData) -> str:
"""show the position of the protein seq"""
var_str = ""

count = -1
prev_aa = -1
for pdata in data.position_details:
count += 1

if not pdata.mapped_pos:
var_str += " "
prev_aa = -1
continue

prot_data = pdata.protein_data

if not prot_data or prot_data.aa_pos < 0:
var_str += " "
prev_aa = -1
continue

if len(var_str) > count:
continue

aa_pos = prot_data.aa_pos

if aa_pos == prev_aa:
var_str += " "
continue

prev_aa = aa_pos

if (aa_pos + 1) % 10 == 0:
var_str += f"{aa_pos+1} "
continue

elif aa_pos == 0:
var_str += f"{aa_pos+1} "
continue

var_str += " "

return var_str
75 changes: 75 additions & 0 deletions src/hgvs/pretty/console/prot_seq_renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from hgvs.pretty.models import VariantData
from hgvs.pretty.console.renderer import BasicRenderer


class ProtSeqRenderer(BasicRenderer):

def legend(self):
legend = "aa seq -> : "
if self.orientation < 0:
legend = "aa seq <- : "
return legend

def display(self, data: VariantData) -> str:
if not data.var_c_or_n:
return ""

from hgvs.pretty.console.constants import ENDC, TGREEN, TRED

var_str = ""
for pdata in data.position_details:

p = pdata.chromosome_pos

if not pdata.mapped_pos:
var_str += " "
continue

ref_base = pdata.ref

c_interval = pdata.c_interval
if not c_interval:
var_str += " "
continue

cig = pdata.cigar_ref
c_offset = pdata.c_offset
if cig == "N" or c_offset != 0:
var_str += " "
continue

if cig == "I":
var_str += "-"
continue

if not ref_base or pdata.tx:
ref_base = pdata.tx

protein_data = pdata.protein_data

if not protein_data:
var_str += " "
continue

aa_char = protein_data.aa_char

# color init met and stop codon if using color:
if protein_data.is_init_met:
if self.config.useColor:
aa_char = TGREEN + aa_char + ENDC
var_str += aa_char
continue
if protein_data.is_stop_codon:
if self.config.useColor:
aa_char = TRED + aa_char + ENDC
var_str += aa_char
continue

if not protein_data.var_p.posedit:
var_str += " "
continue

var_str += aa_char
continue

return var_str
32 changes: 32 additions & 0 deletions src/hgvs/pretty/console/renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from abc import ABC, abstractmethod

from hgvs.pretty.console.constants import ENDC, TPURPLE, TYELLOW


def colorize_hgvs(hgvs_str: str) -> str:
""" Takes a string representation of a hgvs Sequence Variant and renders it with console colors.
"""

spl = hgvs_str.split(":")
var_str = TPURPLE + spl[0] + ENDC
var_str += ":"

sec = spl[1].split(".")
var_str += TYELLOW + sec[0] + ENDC
var_str += "."
var_str += sec[1]

return var_str

class BasicRenderer(ABC):
def __init__(self, config, orientation: int):
self.config = config
self.orientation = orientation

@abstractmethod
def legend(self):
pass

@abstractmethod
def display(self):
pass
Loading
Loading