Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
74 changes: 63 additions & 11 deletions api-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ info:
servers:
- url: 'http://localhost:8080'
tags:
- name: Database
description: IPD-IMGT/HLA DB Information
- name: ARD Reduction
description: Reduce GL String to ARD
- name: CWD Reduction
description: Reduce GL String to CWD (version 2)
- name: MAC
description: Expand/Collapse MAC to/from alleles
- name: DRBX Blender
description: Blend DRBX based on DRB1 and DRB3/4/5
- name: Validation
description: Validate a GL String or Allele
- name: DRBX Blender
description: Blend DRBX based on DRB1 and DRB3/4/5
- name: Broad Splits
description: Broad Split Mappings
- name: Database
description: IPD-IMGT/HLA DB Information
paths:
/version:
get:
Expand Down Expand Up @@ -462,10 +466,58 @@ paths:
Broad/Split mapping not found for the given allele
content:
application/json:
schema:
type: object
properties:
message:
description: Mapping not found
type: string
example: "Broad/Split not found"
schema:
type: object
properties:
message:
description: Mapping not found
type: string
example: "Broad/Split not found"
/similar/{allele_prefix}:
get:
tags:
- Database
operationId: api.similar_controller
summary: Search For Similar Alleles and MACs
description: |
Given a prefix of an allele or MAC, find all the alleles
beginning with the prefix.
parameters:
- name: allele_prefix
in: path
description: |
Prefix of an Allele/MAC with a minimum of locus and a first field
required: true
schema:
type: string
example: A*01:9
responses:
200:
description: List of alleles with the given prefix
content:
application/json:
schema:
type: array
items:
example:
- A*01:91
- A*01:92
- A*01:93
- A*01:94
- A*01:95
- A*01:96
- A*01:97
- A*01:98
- A*01:99
404:
description: |
No matching alleles or MACs found
content:
application/json:
schema:
type: object
properties:
message:
description: No similar alleles
type: string
example: "No similar alleles"
9 changes: 9 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,12 @@ def cwd_redux_controller():

# if no data is sent
return {"message": "No input data provided"}, 404


def similar_controller(allele_prefix: str):
if allele_prefix:
alleles = ard.similar_alleles(allele_prefix)
if alleles:
return alleles, 200
return {"message": "No similar alleles found."}, 400
return {"message": "No input data provided"}, 404
60 changes: 52 additions & 8 deletions pyard/ard.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,25 @@
import sqlite3
import sys
from collections import Counter
from typing import Iterable, List
from typing import Iterable, List, Union

from . import broad_splits, smart_sort
from . import data_repository as dr
from . import db
from .exceptions import InvalidAlleleError, InvalidMACError, InvalidTypingError
from .misc import (
get_n_field_allele,
get_2field_allele,
is_2_field_allele,
validate_reduction_type,
)
from .constants import (
HLA_regex,
VALID_REDUCTION_TYPES,
expression_chars,
DEFAULT_CACHE_SIZE,
G_GROUP_LOCI,
)
from .exceptions import InvalidAlleleError, InvalidMACError, InvalidTypingError
from .misc import (
get_n_field_allele,
get_2field_allele,
is_2_field_allele,
validate_reduction_type,
)

default_config = {
"reduce_serology": True,
Expand Down Expand Up @@ -837,3 +837,47 @@ def get_db_version(self) -> str:
@return:
"""
return dr.get_db_version(self.db_connection)

def similar_alleles(self, prefix: str) -> Union[List, None]:
"""
Given a prefix, find similar alleles or MACs starting with the prefix.
The minimum prefix needs to specify is the locus with a `*`,
and a first field of the allele/MAC.

@param prefix: The prefix for allele or MAC
@return: List of alleles/MACs that start with the prefix
"""

if "*" not in prefix: # Only for those that have locus
return None

locus, fields = prefix.split("*")
# if at least a field is specified after *
if fields:
# Will check only for and after 2 fields
if len(fields.split(":")) == 2:
first_field, mac_prefix = fields.split(":")
if mac_prefix.isalpha(): # Check for MACs
similar_mac_names = db.similar_mac(self.db_connection, mac_prefix)
if similar_mac_names:
locus_prefix = f"{locus}*{first_field}"
# Build all the mac codes with the prefix
mac_codes = [
f"{locus_prefix}:{code}" for code in similar_mac_names
]
# show only the valid macs
real_mac_codes = sorted(
filter(lambda mac: self.is_mac(mac), mac_codes)
)
return real_mac_codes

# find similar alleles
similar_allele_names = db.similar_alleles(self.db_connection, prefix)
if similar_allele_names:
alleles = sorted(
similar_allele_names,
key=functools.cmp_to_key(smart_sort.smart_sort_comparator),
)
return alleles

return None
2 changes: 1 addition & 1 deletion requirements-deploy.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
connexion[swagger-ui]==2.13.0
connexion[swagger-ui, flask]==2.14.2
gunicorn==20.1.0
38 changes: 7 additions & 31 deletions scripts/pyard
Original file line number Diff line number Diff line change
Expand Up @@ -33,40 +33,18 @@ from pyard.exceptions import InvalidAlleleError, InvalidTypingError, InvalidMACE
from pyard.misc import get_data_dir, get_imgt_version


def find_similar_alleles(ard, prefix):
if "*" in prefix: # Only for those that have locus
locus, fields = prefix.split("*")
if fields: # Only if at least a field is specified after *
if len(fields.split(":")) == 2: # Check for MACs
first_field, mac_prefix = fields.split(":")
if mac_prefix.isalpha():
similar_mac_names = similar_mac(ard.db_connection, mac_prefix)
if similar_mac_names:
locus_prefix = f"{locus}*{first_field}"
# TODO: validate all the mac codes with the prefix
# show only the valid macs
for code in sorted(similar_mac_names):
print(f"{locus_prefix}:{code}")
else:
# Nothing after *
sys.exit(2)
def find_similar_alleles(prefix):
alleles = ard.similar_alleles(prefix)
if alleles:
for allele in alleles:
print(allele)
sys.exit(0)
else:
# No *
sys.exit(1)

# find similar alleles
similar_allele_names = similar_alleles(ard.db_connection, prefix)
if similar_allele_names:
for allele in sorted(
similar_allele_names,
key=functools.cmp_to_key(smart_sort.smart_sort_comparator),
):
print(allele)
sys.exit(0)


def lookup_mac_codes():
global e
try:
mac = ard.lookup_mac(args.lookup_mac)
print(mac)
Expand All @@ -76,7 +54,6 @@ def lookup_mac_codes():


def expand_mac_code():
global allele_list, e
try:
allele_list = ard.expand_mac(args.expand_mac)
print(allele_list)
Expand All @@ -100,7 +77,6 @@ def show_version():


def perform_cwd_redux():
global cwd_redux
if args.validate:
ard.validate(args.cwd)
cwd_redux = ard.cwd_redux(args.cwd)
Expand Down Expand Up @@ -202,7 +178,7 @@ if __name__ == "__main__":

# Handle --similar option
if args.similar_allele:
find_similar_alleles(ard, args.similar_allele)
find_similar_alleles(args.similar_allele)

try:
if args.cwd:
Expand Down