Skip to content

Commit

Permalink
Merge pull request #32 from GavinHuttley/develop
Browse files Browse the repository at this point in the history
Testing of the homology db
  • Loading branch information
GavinHuttley authored Nov 16, 2023
2 parents 1830d1a + 8fd0eca commit 97fe2df
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 63 deletions.
42 changes: 20 additions & 22 deletions src/ensembl_lite/_homologydb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

import typing

from typing import Iterable, Sized

from cogent3.core.alignment import SequenceCollection
from rich.progress import track

from ensembl_lite._config import InstalledConfig
from ensembl_lite._db_base import SqliteDbMixin


NoneType = type(None)
OptionalStr = typing.Optional[str]

_HOMOLOGYDB_NAME = "homologies.sqlitedb"
Expand Down Expand Up @@ -46,26 +45,22 @@ def grouped_related(
I assume that for a specific relationship type, a gene can only belong
to one group.
"""
result = {}
# grouped is {gene id: set(group)}. So gene's that belong to the same
# group have the same value
grouped = {}
for record in track(data, description="Grouping related...", transient=True):
pair = [
(record["species_1"], record["gene_id_1"]),
(record["species_2"], record["gene_id_2"]),
]

for member in pair:
if member in result:
# one member, rel has already been encountered
# so we get this value and update it with the new pair
val = result[member]
break
sp1, id1 = record["species_1"], record["gene_id_1"]
sp2, id2 = record["species_2"], record["gene_id_2"]
pair = [(sp1, id1), (sp2, id2)]
if id1 in grouped:
val = grouped[id1]
elif id2 in grouped:
val = grouped[id2]
else:
val = set()

val.update(pair)
for member in pair:
result[member] = val
return [tuple(v) for v in result.values()]
grouped[id1] = grouped[id2] = val
return {frozenset(v) for v in grouped.values()}


# the homology db stores pairwise relationship information
Expand All @@ -88,8 +83,11 @@ def __init__(self, source=":memory:"):
self._init_tables()

def add_records(
self, *, records: typing.Sequence[HomologyRecordType], col_order: Sized[str]
):
self,
*,
records: typing.Sequence,
col_order: typing.Sized[str],
) -> NoneType:
# bulk insert
val_placeholder = ", ".join("?" * len(col_order))
sql = f"INSERT INTO {self.table_name} ({', '.join(col_order)}) VALUES ({val_placeholder})"
Expand All @@ -116,7 +114,7 @@ def get_related_to(

def get_related_groups(
self, relationship_type: str
) -> Iterable[tuple[tuple[str, str]]]:
) -> typing.Iterable[tuple[tuple[str, str]]]:
"""returns all groups of relationship type"""
# get all gene ID's first
sql = f"SELECT * from {self.table_name} WHERE relationship=?"
Expand Down Expand Up @@ -144,4 +142,4 @@ def get_homologous_seqs(
names: list[str],
) -> typing.Iterable[SequenceCollection]:
# todo support ensuring species set present
hdb = load_homology_db(cfg)
hdb = load_homology_db(cfg=cfg)
74 changes: 37 additions & 37 deletions tests/data/one2one_homologies.tsv
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
False gene_stable_id protein_stable_id species identity homology_type homology_gene_stable_id homology_protein_stable_id homology_species homology_identity dn ds goc_score wga_coverage is_high_confidence homology_id
ENSPTRG00000042628 ENSPTRP00000061401 pan_troglodytes 91.3043 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 91.3043 NULL NULL 100 100.00 1 56628198
ENSPTRG00000042639 ENSPTRP00000061398 pan_troglodytes 93.0283 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 93.0283 NULL NULL 100 100.00 1 56625462
ENSPTRG00000042651 ENSPTRP00000061403 pan_troglodytes 90.5473 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 90.5473 NULL NULL 100 100.00 1 56644048
ENSPTRG00000042630 ENSPTRP00000061410 pan_troglodytes 95.977 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 95.977 NULL NULL 75 100.00 1 56640132
ENSPTRG00000042637 ENSPTRP00000061405 pan_troglodytes 93.1579 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 93.1579 NULL NULL 50 100.00 1 56631478
ENSPPYG00000020964 ENSPPYP00000023446 pongo_abelii 84.3478 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 84.3478 NULL NULL 100 0.00 1 56401690
ENSPPYG00000020967 ENSPPYP00000023448 pongo_abelii 89.1068 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 89.1068 NULL NULL 100 0.00 1 56399416
ENSPPYG00000020971 ENSPPYP00000023449 pongo_abelii 82.3627 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 82.0896 NULL NULL 100 0.00 1 56415811
ENSPPYG00000020974 ENSPPYP00000023451 pongo_abelii 90.2632 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 90.2632 NULL NULL 50 0.00 0 56404611
ENSG00000198695 ENSP00000354665 homo_sapiens 97.1264 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 97.1264 NULL NULL 75 100.00 1 56619377
ENSG00000198727 ENSP00000354554 homo_sapiens 92.6316 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 92.6316 NULL NULL 50 100.00 1 56611748
ENSG00000198786 ENSP00000354813 homo_sapiens 90.0498 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 90.0498 NULL NULL 100 100.00 1 56622868
ENSG00000198840 ENSP00000355206 homo_sapiens 93.0435 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 93.0435 NULL NULL 100 100.00 1 56608838
ENSG00000198886 ENSP00000354961 homo_sapiens 94.9891 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 94.9891 NULL NULL 100 100.00 1 56606592
ENSMMUG00000065353 ENSMMUP00000081256 macaca_mulatta 78.2609 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 78.2609 NULL NULL 100 100.00 1 76881074
ENSMMUG00000065387 ENSMMUP00000081261 macaca_mulatta 76.0349 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 76.0349 NULL NULL 100 100.00 1 76878860
ENSMMUG00000065354 ENSMMUP00000081255 macaca_mulatta 75.2902 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 75.2902 NULL NULL 100 100.00 1 76894845
ENSMMUG00000065382 ENSMMUP00000081249 macaca_mulatta 80.2632 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 80.2632 NULL NULL 50 100.00 1 76883952
ENSMICG00000027348 ENSMICP00000016336 microcebus_murinus 66.9565 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 66.9565 NULL NULL 100 100.00 1 83625751
ENSMICG00000032407 ENSMICP00000040348 microcebus_murinus 71.4597 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 71.4597 NULL NULL 100 100.00 1 83623377
ENSMICG00000026565 ENSMICP00000027021 microcebus_murinus 69.8176 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 69.8176 NULL NULL 100 100.00 1 83640006
ENSMICG00000028801 ENSMICP00000026522 microcebus_murinus 50 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 50 NULL NULL 75 100.00 1 83636541
ENSMICG00000037851 ENSMICP00000022746 microcebus_murinus 78.3641 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 78.1579 NULL NULL 50 100.00 1 83628828
ENSMFAG00000065538 ENSMFAP00000058497 macaca_fascicularis 80 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 80 NULL NULL 100 0.00 1 75714938
ENSMFAG00000057489 ENSMFAP00000063536 macaca_fascicularis 75.5991 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 75.5991 NULL NULL 100 0.00 1 75712710
ENSMFAG00000053671 ENSMFAP00000051998 macaca_fascicularis 75.4561 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 75.4561 NULL NULL 100 0.00 1 75728456
ENSMFAG00000062540 ENSMFAP00000058831 macaca_fascicularis 80.7895 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 80.7895 NULL NULL 50 0.00 0 75717779
ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 76.0349 ortholog_one2one ENSCSAG00000000028 ENSCSAP00000000010 chlorocebus_sabaeus 76.0349 NULL NULL 100 100.00 1 84611826
ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 74.6269 ortholog_one2one ENSCSAG00000000032 ENSCSAP00000000011 chlorocebus_sabaeus 74.7508 NULL NULL 100 100.00 1 84627614
ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 81.0345 ortholog_one2one ENSCSAG00000000033 ENSCSAP00000000012 chlorocebus_sabaeus 81.5029 NULL NULL 75 100.00 1 84624249
ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 82.6316 ortholog_one2one ENSCSAG00000000035 ENSCSAP00000000013 chlorocebus_sabaeus 82.6316 NULL NULL 50 100.00 1 84616943
ENSPPAG00000000025 ENSPPAP00000000008 pan_paniscus 93.913 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 93.913 NULL NULL 100 100.00 1 56439973
ENSPPAG00000000028 ENSPPAP00000000010 pan_paniscus 94.3355 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 94.3355 NULL NULL 100 100.00 1 56437537
ENSPPAG00000000032 ENSPPAP00000000011 pan_paniscus 90.8789 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 90.8789 NULL NULL 100 100.00 1 56454514
ENSPPAG00000000033 ENSPPAP00000000012 pan_paniscus 97.1264 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 97.1264 NULL NULL 75 100.00 1 56450900
ENSPPAG00000000035 ENSPPAP00000000013 pan_paniscus 92.3684 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 92.3684 NULL NULL 50 100.00 1 56442998
gene_stable_id protein_stable_id species identity homology_type homology_gene_stable_id homology_protein_stable_id homology_species homology_identity dn ds goc_score wga_coverage is_high_confidence homology_id
ENSPTRG00000042628 ENSPTRP00000061401 pan_troglodytes 91.3043 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 91.3043 NULL NULL 100 100.0 1 56628198
ENSPTRG00000042639 ENSPTRP00000061398 pan_troglodytes 93.0283 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 93.0283 NULL NULL 100 100.0 1 56625462
ENSPTRG00000042651 ENSPTRP00000061403 pan_troglodytes 90.5473 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 90.5473 NULL NULL 100 100.0 1 56644048
ENSPTRG00000042630 ENSPTRP00000061410 pan_troglodytes 95.977 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 95.977 NULL NULL 75 100.0 1 56640132
ENSPTRG00000042637 ENSPTRP00000061405 pan_troglodytes 93.1579 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 93.1579 NULL NULL 50 100.0 1 56631478
ENSPPYG00000020964 ENSPPYP00000023446 pongo_abelii 84.3478 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 84.3478 NULL NULL 100 0.0 1 56401690
ENSPPYG00000020967 ENSPPYP00000023448 pongo_abelii 89.1068 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 89.1068 NULL NULL 100 0.0 1 56399416
ENSPPYG00000020971 ENSPPYP00000023449 pongo_abelii 82.3627 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 82.0896 NULL NULL 100 0.0 1 56415811
ENSPPYG00000020974 ENSPPYP00000023451 pongo_abelii 90.2632 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 90.2632 NULL NULL 50 0.0 0 56404611
ENSG00000198695 ENSP00000354665 homo_sapiens 97.1264 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 97.1264 NULL NULL 75 100.0 1 56619377
ENSG00000198727 ENSP00000354554 homo_sapiens 92.6316 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 92.6316 NULL NULL 50 100.0 1 56611748
ENSG00000198786 ENSP00000354813 homo_sapiens 90.0498 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 90.0498 NULL NULL 100 100.0 1 56622868
ENSG00000198840 ENSP00000355206 homo_sapiens 93.0435 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 93.0435 NULL NULL 100 100.0 1 56608838
ENSG00000198886 ENSP00000354961 homo_sapiens 94.9891 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 94.9891 NULL NULL 100 100.0 1 56606592
ENSMMUG00000065353 ENSMMUP00000081256 macaca_mulatta 78.2609 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 78.2609 NULL NULL 100 100.0 1 76881074
ENSMMUG00000065387 ENSMMUP00000081261 macaca_mulatta 76.0349 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 76.0349 NULL NULL 100 100.0 1 76878860
ENSMMUG00000065354 ENSMMUP00000081255 macaca_mulatta 75.2902 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 75.2902 NULL NULL 100 100.0 1 76894845
ENSMMUG00000065382 ENSMMUP00000081249 macaca_mulatta 80.2632 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 80.2632 NULL NULL 50 100.0 1 76883952
ENSMICG00000027348 ENSMICP00000016336 microcebus_murinus 66.9565 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 66.9565 NULL NULL 100 100.0 1 83625751
ENSMICG00000032407 ENSMICP00000040348 microcebus_murinus 71.4597 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 71.4597 NULL NULL 100 100.0 1 83623377
ENSMICG00000026565 ENSMICP00000027021 microcebus_murinus 69.8176 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 69.8176 NULL NULL 100 100.0 1 83640006
ENSMICG00000028801 ENSMICP00000026522 microcebus_murinus 50.0 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 50.0 NULL NULL 75 100.0 1 83636541
ENSMICG00000037851 ENSMICP00000022746 microcebus_murinus 78.3641 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 78.1579 NULL NULL 50 100.0 1 83628828
ENSMFAG00000065538 ENSMFAP00000058497 macaca_fascicularis 80.0 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 80.0 NULL NULL 100 0.0 1 75714938
ENSMFAG00000057489 ENSMFAP00000063536 macaca_fascicularis 75.5991 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 75.5991 NULL NULL 100 0.0 1 75712710
ENSMFAG00000053671 ENSMFAP00000051998 macaca_fascicularis 75.4561 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 75.4561 NULL NULL 100 0.0 1 75728456
ENSMFAG00000062540 ENSMFAP00000058831 macaca_fascicularis 80.7895 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 80.7895 NULL NULL 50 0.0 0 75717779
ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 76.0349 ortholog_one2one ENSCSAG00000000028 ENSCSAP00000000010 chlorocebus_sabaeus 76.0349 NULL NULL 100 100.0 1 84611826
ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 74.6269 ortholog_one2one ENSCSAG00000000032 ENSCSAP00000000011 chlorocebus_sabaeus 74.7508 NULL NULL 100 100.0 1 84627614
ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 81.0345 ortholog_one2one ENSCSAG00000000033 ENSCSAP00000000012 chlorocebus_sabaeus 81.5029 NULL NULL 75 100.0 1 84624249
ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 82.6316 ortholog_one2one ENSCSAG00000000035 ENSCSAP00000000013 chlorocebus_sabaeus 82.6316 NULL NULL 50 100.0 1 84616943
ENSPPAG00000000025 ENSPPAP00000000008 pan_paniscus 93.913 ortholog_one2one ENSGGOG00000026757 ENSGGOP00000021306 gorilla_gorilla 93.913 NULL NULL 100 100.0 1 56439973
ENSPPAG00000000028 ENSPPAP00000000010 pan_paniscus 94.3355 ortholog_one2one ENSGGOG00000025053 ENSGGOP00000024209 gorilla_gorilla 94.3355 NULL NULL 100 100.0 1 56437537
ENSPPAG00000000032 ENSPPAP00000000011 pan_paniscus 90.8789 ortholog_one2one ENSGGOG00000022688 ENSGGOP00000022538 gorilla_gorilla 90.8789 NULL NULL 100 100.0 1 56454514
ENSPPAG00000000033 ENSPPAP00000000012 pan_paniscus 97.1264 ortholog_one2one ENSGGOG00000026221 ENSGGOP00000028201 gorilla_gorilla 97.1264 NULL NULL 75 100.0 1 56450900
ENSPPAG00000000035 ENSPPAP00000000013 pan_paniscus 92.3684 ortholog_one2one ENSGGOG00000024015 ENSGGOP00000022734 gorilla_gorilla 92.3684 NULL NULL 50 100.0 1 56442998
87 changes: 83 additions & 4 deletions tests/test_homologydb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

from cogent3 import load_table

from ensembl_lite._homologydb import _HOMOLOGYDB_NAME, HomologyDb
from ensembl_lite._homologydb import (
_HOMOLOGYDB_NAME,
HomologyDb,
HomologyRecordType,
grouped_related,
)
from ensembl_lite.install import LoadHomologies


Expand Down Expand Up @@ -39,12 +44,11 @@ def o2o_db(DATA_DIR, tmp_dir):
table = load_table(raw).get_columns(loader.src_cols)

table = table.with_new_header(loader.src_cols, loader.dest_col[:-1])
expect = _make_expected_o2o(table)

data = loader([raw])
homdb = HomologyDb(tmp_dir / _HOMOLOGYDB_NAME)
homdb.add_records(records=data, col_order=loader.dest_col)
return homdb, expect
return homdb, table


@pytest.mark.parametrize(
Expand All @@ -58,7 +62,82 @@ def o2o_db(DATA_DIR, tmp_dir):
),
)
def test_hdb(o2o_db, gene_id):
homdb, expect = o2o_db
homdb, table = o2o_db
expect = _make_expected_o2o(table)

got = homdb.get_related_to(gene_id=gene_id, relationship_type="ortholog_one2one")
assert got == expect[gene_id]


@pytest.fixture
def orth_records():
common = dict(relationship="ortholog_one2one")
return [
HomologyRecordType(
species_1="a", gene_id_1="1", species_2="b", gene_id_2="2", **common
), # grp 1
HomologyRecordType(
species_1="b", gene_id_1="2", species_2="c", gene_id_2="3", **common
), # grp 1
HomologyRecordType(
species_1="d", gene_id_1="4", species_2="e", gene_id_2="5", **common
),
]


@pytest.fixture
def hom_records(orth_records):
return orth_records + [
HomologyRecordType(
species_1="a",
gene_id_1="6",
species_2="e",
gene_id_2="7",
relationship="ortholog_one2many",
),
]


def _reduced_to_ids(groups):
return [[i for _, i in group] for group in groups]


def test_hdb_get_related_groups(o2o_db):
homdb, table = o2o_db
got = homdb.get_related_groups(relationship_type="ortholog_one2one")
groups = _reduced_to_ids(got)
assert len(groups) == 5


@pytest.fixture
def hom_hdb(hom_records):
col_order = (
"relationship",
"species_1",
"gene_id_1",
"species_2",
"gene_id_2",
)
records = [[r[c] for c in col_order] for r in hom_records]
hdb = HomologyDb(source=":memory:")
hdb.add_records(records=records, col_order=col_order)
return hdb


def test_group_related(hom_records):
orths = [r for r in hom_records if r["relationship"] == "ortholog_one2one"]
got = grouped_related(orths)
expect = {
frozenset([("a", "1"), ("b", "2"), ("c", "3")]),
frozenset([("d", "4"), ("e", "5")]),
}
assert got == expect


def test_homology_db(hom_hdb):
got = hom_hdb.get_related_groups("ortholog_one2one")
expect = {
frozenset([("a", "1"), ("b", "2"), ("c", "3")]),
frozenset([("d", "4"), ("e", "5")]),
}
assert got == expect

0 comments on commit 97fe2df

Please sign in to comment.