Skip to content

Commit d43a035

Browse files
authored
Merge pull request #289 from pbashyal-nmdp/similar-endpoint
Create `similar` endpoint
2 parents b1a995d + 9da850c commit d43a035

File tree

5 files changed

+132
-51
lines changed

5 files changed

+132
-51
lines changed

api-spec.yaml

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,20 @@ info:
66
servers:
77
- url: 'http://localhost:8080'
88
tags:
9-
- name: Database
10-
description: IPD-IMGT/HLA DB Information
119
- name: ARD Reduction
1210
description: Reduce GL String to ARD
11+
- name: CWD Reduction
12+
description: Reduce GL String to CWD (version 2)
1313
- name: MAC
1414
description: Expand/Collapse MAC to/from alleles
15-
- name: DRBX Blender
16-
description: Blend DRBX based on DRB1 and DRB3/4/5
1715
- name: Validation
1816
description: Validate a GL String or Allele
17+
- name: DRBX Blender
18+
description: Blend DRBX based on DRB1 and DRB3/4/5
19+
- name: Broad Splits
20+
description: Broad Split Mappings
21+
- name: Database
22+
description: IPD-IMGT/HLA DB Information
1923
paths:
2024
/version:
2125
get:
@@ -462,10 +466,58 @@ paths:
462466
Broad/Split mapping not found for the given allele
463467
content:
464468
application/json:
465-
schema:
466-
type: object
467-
properties:
468-
message:
469-
description: Mapping not found
470-
type: string
471-
example: "Broad/Split not found"
469+
schema:
470+
type: object
471+
properties:
472+
message:
473+
description: Mapping not found
474+
type: string
475+
example: "Broad/Split not found"
476+
/similar/{allele_prefix}:
477+
get:
478+
tags:
479+
- Database
480+
operationId: api.similar_controller
481+
summary: Search For Similar Alleles and MACs
482+
description: |
483+
Given a prefix of an allele or MAC, find all the alleles
484+
beginning with the prefix.
485+
parameters:
486+
- name: allele_prefix
487+
in: path
488+
description: |
489+
Prefix of an Allele/MAC with a minimum of locus and a first field
490+
required: true
491+
schema:
492+
type: string
493+
example: A*01:9
494+
responses:
495+
200:
496+
description: List of alleles with the given prefix
497+
content:
498+
application/json:
499+
schema:
500+
type: array
501+
items:
502+
example:
503+
- A*01:91
504+
- A*01:92
505+
- A*01:93
506+
- A*01:94
507+
- A*01:95
508+
- A*01:96
509+
- A*01:97
510+
- A*01:98
511+
- A*01:99
512+
404:
513+
description: |
514+
No matching alleles or MACs found
515+
content:
516+
application/json:
517+
schema:
518+
type: object
519+
properties:
520+
message:
521+
description: No similar alleles
522+
type: string
523+
example: "No similar alleles"

api.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,12 @@ def cwd_redux_controller():
143143

144144
# if no data is sent
145145
return {"message": "No input data provided"}, 404
146+
147+
148+
def similar_controller(allele_prefix: str):
149+
if allele_prefix:
150+
alleles = ard.similar_alleles(allele_prefix)
151+
if alleles:
152+
return alleles, 200
153+
return {"message": "No similar alleles found."}, 400
154+
return {"message": "No input data provided"}, 404

pyard/ard.py

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,25 @@
2626
import sqlite3
2727
import sys
2828
from collections import Counter
29-
from typing import Iterable, List
29+
from typing import Iterable, List, Union
3030

3131
from . import broad_splits, smart_sort
3232
from . import data_repository as dr
3333
from . import db
34-
from .exceptions import InvalidAlleleError, InvalidMACError, InvalidTypingError
35-
from .misc import (
36-
get_n_field_allele,
37-
get_2field_allele,
38-
is_2_field_allele,
39-
validate_reduction_type,
40-
)
4134
from .constants import (
4235
HLA_regex,
4336
VALID_REDUCTION_TYPES,
4437
expression_chars,
4538
DEFAULT_CACHE_SIZE,
4639
G_GROUP_LOCI,
4740
)
41+
from .exceptions import InvalidAlleleError, InvalidMACError, InvalidTypingError
42+
from .misc import (
43+
get_n_field_allele,
44+
get_2field_allele,
45+
is_2_field_allele,
46+
validate_reduction_type,
47+
)
4848

4949
default_config = {
5050
"reduce_serology": True,
@@ -851,3 +851,47 @@ def get_db_version(self) -> str:
851851
@return:
852852
"""
853853
return dr.get_db_version(self.db_connection)
854+
855+
def similar_alleles(self, prefix: str) -> Union[List, None]:
856+
"""
857+
Given a prefix, find similar alleles or MACs starting with the prefix.
858+
The minimum prefix needs to specify is the locus with a `*`,
859+
and a first field of the allele/MAC.
860+
861+
@param prefix: The prefix for allele or MAC
862+
@return: List of alleles/MACs that start with the prefix
863+
"""
864+
865+
if "*" not in prefix: # Only for those that have locus
866+
return None
867+
868+
locus, fields = prefix.split("*")
869+
# if at least a field is specified after *
870+
if fields:
871+
# Will check only for and after 2 fields
872+
if len(fields.split(":")) == 2:
873+
first_field, mac_prefix = fields.split(":")
874+
if mac_prefix.isalpha(): # Check for MACs
875+
similar_mac_names = db.similar_mac(self.db_connection, mac_prefix)
876+
if similar_mac_names:
877+
locus_prefix = f"{locus}*{first_field}"
878+
# Build all the mac codes with the prefix
879+
mac_codes = [
880+
f"{locus_prefix}:{code}" for code in similar_mac_names
881+
]
882+
# show only the valid macs
883+
real_mac_codes = sorted(
884+
filter(lambda mac: self.is_mac(mac), mac_codes)
885+
)
886+
return real_mac_codes
887+
888+
# find similar alleles
889+
similar_allele_names = db.similar_alleles(self.db_connection, prefix)
890+
if similar_allele_names:
891+
alleles = sorted(
892+
similar_allele_names,
893+
key=functools.cmp_to_key(smart_sort.smart_sort_comparator),
894+
)
895+
return alleles
896+
897+
return None

requirements-deploy.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
connexion[swagger-ui]==2.13.0
1+
connexion[swagger-ui, flask]==2.14.2
22
gunicorn==20.1.0

scripts/pyard

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -33,40 +33,18 @@ from pyard.exceptions import InvalidAlleleError, InvalidTypingError, InvalidMACE
3333
from pyard.misc import get_data_dir, get_imgt_version
3434

3535

36-
def find_similar_alleles(ard, prefix):
37-
if "*" in prefix: # Only for those that have locus
38-
locus, fields = prefix.split("*")
39-
if fields: # Only if at least a field is specified after *
40-
if len(fields.split(":")) == 2: # Check for MACs
41-
first_field, mac_prefix = fields.split(":")
42-
if mac_prefix.isalpha():
43-
similar_mac_names = similar_mac(ard.db_connection, mac_prefix)
44-
if similar_mac_names:
45-
locus_prefix = f"{locus}*{first_field}"
46-
# TODO: validate all the mac codes with the prefix
47-
# show only the valid macs
48-
for code in sorted(similar_mac_names):
49-
print(f"{locus_prefix}:{code}")
50-
else:
51-
# Nothing after *
52-
sys.exit(2)
36+
def find_similar_alleles(prefix):
37+
alleles = ard.similar_alleles(prefix)
38+
if alleles:
39+
for allele in alleles:
40+
print(allele)
41+
sys.exit(0)
5342
else:
5443
# No *
5544
sys.exit(1)
5645

57-
# find similar alleles
58-
similar_allele_names = similar_alleles(ard.db_connection, prefix)
59-
if similar_allele_names:
60-
for allele in sorted(
61-
similar_allele_names,
62-
key=functools.cmp_to_key(smart_sort.smart_sort_comparator),
63-
):
64-
print(allele)
65-
sys.exit(0)
66-
6746

6847
def lookup_mac_codes():
69-
global e
7048
try:
7149
mac = ard.lookup_mac(args.lookup_mac)
7250
print(mac)
@@ -76,7 +54,6 @@ def lookup_mac_codes():
7654

7755

7856
def expand_mac_code():
79-
global allele_list, e
8057
try:
8158
allele_list = ard.expand_mac(args.expand_mac)
8259
print(allele_list)
@@ -100,7 +77,6 @@ def show_version():
10077

10178

10279
def perform_cwd_redux():
103-
global cwd_redux
10480
if args.validate:
10581
ard.validate(args.cwd)
10682
cwd_redux = ard.cwd_redux(args.cwd)
@@ -202,7 +178,7 @@ if __name__ == "__main__":
202178

203179
# Handle --similar option
204180
if args.similar_allele:
205-
find_similar_alleles(ard, args.similar_allele)
181+
find_similar_alleles(args.similar_allele)
206182

207183
try:
208184
if args.cwd:

0 commit comments

Comments
 (0)