submit_blast_controller.py 7.28 KB
Newer Older
David Mendez's avatar
David Mendez committed
1
2
3
"""
Module that describes and handles the requests concerned with the blast search submission
"""
4
from flask import request
David Mendez's avatar
David Mendez committed
5
from flask_restx import Namespace, Resource, fields
6

7
from app.models import delayed_job_models
8
from app.namespaces.job_submission.services import job_submission_service
9
10
11
12
13
14
15
16
17
18
19
20
from app.namespaces.job_submission.shared_marshalls import BASE_SUBMISSION_RESPONSE

API = Namespace('submit/blast', description='Namespace to submit a BLAST job')

BLAST_JOB = API.model('BLASTJob', {
    'matrix': fields.String(description='(Protein searches) The substitution matrix used for scoring alignments when '
                                        'searching the database.', example='BLOSUM45',
                            enum=['BLOSUM45', 'BLOSUM50', 'BLOSUM62', 'BLOSUM80', 'BLOSUM90', 'PAM30', 'PAM70',
                                  'PAM250', 'NONE']),
    'alignments': fields.Integer(description='Maximum number of match alignments reported in the result output.',
                                 example=50, enum=[5, 10, 20, 50, 100, 150, 200, 500, 750, 1000], min=5, max=1000),
    'scores': fields.Integer(description='Maximum number of match score summaries reported in the result output.',
David Mendez's avatar
David Mendez committed
21
                             example=50, enum=[5, 10, 20, 50, 100, 150, 200, 500, 750, 1000], min=5, max=1000),
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    'exp': fields.String(description='Limits the number of scores and alignments reported based on the expectation '
                                     'value. This is the maximum number of times the match is expected to occur by '
                                     'chance.', example='10', enum=['1e-200', '1e-100', '1e-50', '1e-10', '1e-5',
                                                                    '1e-4', '1e-3', '1e-2', '1e-1', '1.0', '10', '100',
                                                                    '1000']),
    'dropoff': fields.Integer(description='The amount a score can drop before gapped extension of word hits is halted',
                              example=0, min=0, max=10),
    'gapopen': fields.Integer(description='Penalty taken away from the score when a gap is created in sequence. '
                                          'Increasing the gap openning penalty will decrease the number of gaps in the '
                                          'final alignment.',
                              example=-1, min=-1, max=25),
    'gapext': fields.Integer(description='Penalty taken away from the score for each base or residue in the gap. '
                                         'Increasing the gap extension penalty favors short gaps in the final alignment'
                                         ', conversly decreasing the gap extension penalty favors long gaps in the '
                                         'final alignment.',
                             example=-1, min=-1, max=10),
    'filter': fields.String(description='Filter regions of low sequence complexity. This can avoid issues with low '
                                        'complexity sequences where matches are found due to composition rather than '
                                        'meaningful sequence similarity. However in some cases filtering also masks '
                                        'regions of interest and so should be used with caution.', example='F',
                            enum=['F', 'T']),
    'seqrange': fields.String(description='Specify a range or section of the input sequence to use in the search. '
                                          'Example: Specifying "34-89" in an input sequence of total length 100, will '
                                          'tell BLAST to only use residues 34 to 89, inclusive.',
                              example='START-END'),
    'gapalign': fields.String(description='Filter regions of low sequence complexity. This can avoid issues with low ',
                              example='true',
                              enum=['true', 'false']),
    'wordsize': fields.Integer(description='Word size for wordfinder algorithm',
                               example=6, min=6, max=28),
    'taxids': fields.String(description='Specify one or more TaxIDs so that the BLAST search becomes taxonomically '
                                        'aware.', example=''),
    'compstats': fields.String(description='se composition-based statistics.',
                               example='F', enum=['F', 'D', '1', '2', '3']),
    'align': fields.Integer(description='Formatting for the alignments',
David Mendez's avatar
David Mendez committed
57
                            example=0, min=0, max=12),
58
59
60
61
62
63
64
    'sequence': fields.String(description='The query sequence can be entered directly into this form. The sequence '
                                          'can be in GCG, FASTA, EMBL (Nucleotide only), GenBank, PIR, NBRF, PHYLIP '
                                          'or UniProtKB/Swiss-Prot (Protein only) format. A partially formatted '
                                          'sequence is not accepted. Adding a return to the end of the sequence may '
                                          'help certain applications understand the input. Note that directly using '
                                          'data from word processors may yield unpredictable results as hidden/control '
                                          'characters may be present.',
David Mendez's avatar
David Mendez committed
65
66
67
68
69
70
71
72
73
74
75
76
77
                              example='>sp|P35858|ALS_HUMAN Insulin-like growth factor-binding protein complex acid '
                                      'labile subunit OS=Homo sapiens GN=IGFALS PE=1 SV=1\n'
                                      'MALRKGGLALALLLLSWVALGPRSLEGADPGTPGEAEGPACPAACVCSYDDDADELSVFC\n'
                                      'SSRNLTRLPDGVPGGTQALWLDGNNLSSVPPAAFQNLSSLGFLNLQGGQLGSLEPQALLG\n'
                                      'LENLCHLHLERNQLRSLALGTFAHTPALASLGLSNNRLSRLEDGLFEGLGSLWDLNLGWN\n'
                                      'SLAVLPDAAFRGLGSLRELVLAGNRLAYLQPALFSGLAELRELDLSRNALRAIKANVFVQ\n'
                                      'LPRLQKLYLDRNLIAAVAPGAFLGLKALRWLDLSHNRVAGLLEDTFPGLLGLRVLRLSHN\n'
                                      'AIASLRPRTFKDLHFLEELQLGHNRIRQLAERSFEGLGQLEVLTLDHNQLQEVKAGAFLG\n'
                                      'LTNVAVMNLSGNCLRNLPEQVFRGLGKLHSLHLEGSCLGRIRPHTFTGLSGLRRLFLKDN\n'
                                      'GLVGIEEQSLWGLAELLELDLTSNQLTHLPHRLFQGLGKLEYLLLSRNRLAELPADALGP\n'
                                      'LQRAFWLDVSHNRLEALPNSLLAPLGRLRYLSLRNNSLRTFTPQPPGLERLWLEGNPWDC\n'
                                      'GCPLKALRDFALQNPSAVPRFVQAICEGDDCQPPAYTYNNITCASPPEVVGLDLRDLSEA\n'
                                      'HFAPC'),
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
})

SUBMISSION_RESPONSE = API.inherit('SubmissionResponse', BASE_SUBMISSION_RESPONSE)


@API.route('/')
class SubmitBLASTJob(Resource):
    """
        Resource that handles BLAST search job submission requests
    """
    job_type = delayed_job_models.JobTypes.BLAST

    @API.expect(BLAST_JOB)
    @API.doc(body=BLAST_JOB)
    @API.marshal_with(BASE_SUBMISSION_RESPONSE)
    def post(self):  # pylint: disable=no-self-use
        """
        Submits a job to the queue.
        :return: a json response with the result of the submission
        """

        json_data = request.json
        job_params = {
            **json_data,
            'search_type': str(self.job_type),
        }
        response = job_submission_service.submit_job(self.job_type, job_params)
        return response