scout/adapter/mongo/query.py
def build_query(self, case_id, query=None, variant_ids=None, category='snv'):
        """Build a mongo query

        These are the different query options:
            {
                'genetic_models': list,
                'chrom': str,
                'thousand_genomes_frequency': float,
                'exac_frequency': float,
                'clingen_ngi': int,
                'cadd_score': float,
                'cadd_inclusive": boolean,
                'genetic_models': list(str),
                'hgnc_symbols': list,
                'region_annotations': list,
                'functional_annotations': list,
                'clinsig': list,
                'clinsig_confident_always_returned': boolean,
                'variant_type': str(('research', 'clinical')),
                'chrom': str,
                'start': int,
                'end': int,
                'svtype': list,
                'size': int,
                'size_shorter': boolean,
                'gene_panels': list(str),
                'mvl_tag": boolean,
                'decipher": boolean,
            }

        Arguments:
            case_id(str)
            query(dict): a dictionary of query filters specified by the users
            variant_ids(list(str)): A list of md5 variant ids

        Returns:
            mongo_query : A dictionary in the mongo query format

        """
        query = query or {}
        mongo_query = {}
        gene_query = None

        ##### Base query params

        # set up the fundamental query params: case_id, category, type and
        # restrict to list of variants (if var list is provided)
        for criterion in FUNDAMENTAL_CRITERIA:
            if criterion == 'case_id':
                LOG.debug("Building a mongo query for %s" % case_id)
                mongo_query['case_id'] = case_id

            elif criterion == 'variant_ids' and variant_ids:
                LOG.debug("Adding variant_ids %s to query" % ', '.join(variant_ids))
                mongo_query['variant_id'] = {'$in': variant_ids}

            elif criterion == 'category':
                LOG.debug("Querying category %s" % category)
                mongo_query['category'] = category

            elif criterion == 'variant_type':
                mongo_query['variant_type'] = query.get('variant_type', 'clinical')
                LOG.debug("Set variant type to %s", mongo_query['variant_type'])

            # Requests to filter based on gene panels, hgnc_symbols or
            # coordinate ranges must always be honored. They are always added to
            # query as top level, implicit '$and'. When both hgnc_symbols and a
            # panel is used, addition of this is delayed until after the rest of
            # the query content is clear.

            elif criterion in ['hgnc_symbols', 'gene_panels'] and gene_query is None:
                gene_query = self.gene_filter(query, mongo_query)

            elif criterion == 'chrom' and query.get('chrom'): # filter by coordinates
                self.coordinate_filter(query, mongo_query)

            elif criterion == 'variant_ids' and variant_ids:
                LOG.debug("Adding variant_ids %s to query" % ', '.join(variant_ids))
                mongo_query['variant_id'] = {'$in': variant_ids}

            ##### end of fundamental query params

        ##### start of the custom query params
        # there is only 'clinsig' criterion among the primary terms right now
        primary_terms = False

        # gnomad_frequency, local_obs, clingen_ngi, swegen, spidex_human, cadd_score, genetic_models, mvl_tag
        # functional_annotations, region_annotations, size, svtype, decipher, depth, alt_count, control_frequency
        secondary_terms = False

        # check if any of the primary criteria was specified in the query
        for term in PRIMARY_CRITERIA:
            if query.get(term):
                primary_terms = True

        # check if any of the secondary criteria was specified in the query:
        for term in SECONDARY_CRITERIA:
            if query.get(term):
                secondary_terms = True

        if primary_terms is True:
            clinsign_filter = self.clinsig_query(query, mongo_query)

        # Secondary, excluding filter criteria will hide variants in general,
        # but can be overridden by an including, major filter criteria
        # such as a Pathogenic ClinSig.
        if secondary_terms is True:
            secondary_filter = self.secondary_query(query, mongo_query)

            # If there are no primary criteria given, all secondary criteria are added as a
            # top level '$and' to the query.
            if primary_terms is False:
                if gene_query:
                    mongo_query['$and'] = [ {'$or': gene_query}, {'$and': secondary_filter}]
                else:
                    mongo_query['$and'] = secondary_filter

            # If there is only one primary criterion given without any secondary, it will also be
            # added as a top level '$and'.
            # Otherwise, primary criteria are added as a high level '$or' and all secondary criteria
            # are joined together with them as a single lower level '$and'.
            if primary_terms is True: # clinsig is specified

                # Given a request to always return confident clinical variants,
                # add the clnsig query as a major criteria, but only
                # trust clnsig entries with trusted revstat levels.
                if query.get('clinsig_confident_always_returned') == True:
                    if gene_query:
                        mongo_query['$and'] = [
                            {'$or': gene_query},
                            {
                                '$or': [
                                    {'$and': secondary_filter}, clinsign_filter
                                ]
                            }
                        ]
                    else:
                        mongo_query['$or'] = [ {'$and': secondary_filter}, clinsign_filter ]
                else: # clisig terms are provided but no need for trusted revstat levels
                    secondary_filter.append(clinsign_filter)
                    if gene_query:
                        mongo_query['$and'] = [ {'$or': gene_query}, {'$and': secondary_filter}]
                    else:
                        mongo_query['$and'] = secondary_filter

        elif primary_terms is True: # clisig is provided without secondary terms query
            # use implicit and
            mongo_query['clnsig'] = clinsign_filter['clnsig']
            if gene_query:
                mongo_query['$and'] = [{ '$or': gene_query }]

        elif gene_query: # no primary or secondary filters provided
            mongo_query['$and'] = [{ '$or': gene_query }]

        LOG.info("mongo query: %s", mongo_query)

        return mongo_query
def build_query(self, case_id, query=None, variant_ids=None, category='snv'):
        """Build a mongo query

        These are the different query options:
            {
                'genetic_models': list,
                'chrom': str,
                'thousand_genomes_frequency': float,
                'exac_frequency': float,
                'clingen_ngi': int,
                'cadd_score': float,
                'cadd_inclusive": boolean,
                'genetic_models': list(str),
                'hgnc_symbols': list,
                'region_annotations': list,
                'functional_annotations': list,
                'clinsig': list,
                'clinsig_confident_always_returned': boolean,
                'variant_type': str(('research', 'clinical')),
                'chrom': str,
                'start': int,
                'end': int,
                'svtype': list,
                'size': int,
                'size_shorter': boolean,
                'gene_panels': list(str),
                'mvl_tag": boolean,
                'decipher": boolean,
            }

        Arguments:
            case_id(str)
            query(dict): a dictionary of query filters specified by the users
            variant_ids(list(str)): A list of md5 variant ids

        Returns:
            mongo_query : A dictionary in the mongo query format

        """
        query = query or {}
        mongo_query = {}
        gene_query = None

        ##### Base query params

        # set up the fundamental query params: case_id, category, type and
        # restrict to list of variants (if var list is provided)
        for criterion in FUNDAMENTAL_CRITERIA:
            if criterion == 'case_id':
                LOG.debug("Building a mongo query for %s" % case_id)
                mongo_query['case_id'] = case_id

            elif criterion == 'variant_ids' and variant_ids:
                LOG.debug("Adding variant_ids %s to query" % ', '.join(variant_ids))
                mongo_query['variant_id'] = {'$in': variant_ids}

            elif criterion == 'category':
                LOG.debug("Querying category %s" % category)
                mongo_query['category'] = category

            elif criterion == 'variant_type':
                mongo_query['variant_type'] = query.get('variant_type', 'clinical')
                LOG.debug("Set variant type to %s", mongo_query['variant_type'])

            # Requests to filter based on gene panels, hgnc_symbols or
            # coordinate ranges must always be honored. They are always added to
            # query as top level, implicit '$and'. When both hgnc_symbols and a
            # panel is used, addition of this is delayed until after the rest of
            # the query content is clear.

            elif criterion in ['hgnc_symbols', 'gene_panels'] and gene_query is None:
                gene_query = self.gene_filter(query, mongo_query)

            elif criterion == 'chrom' and query.get('chrom'): # filter by coordinates
                self.coordinate_filter(query, mongo_query)

            elif criterion == 'variant_ids' and variant_ids:
                LOG.debug("Adding variant_ids %s to query" % ', '.join(variant_ids))
                mongo_query['variant_id'] = {'$in': variant_ids}

            ##### end of fundamental query params

        ##### start of the custom query params
        # there is only 'clinsig' criterion among the primary terms right now
        primary_terms = False

        # gnomad_frequency, local_obs, clingen_ngi, swegen, spidex_human, cadd_score, genetic_models, mvl_tag
        # functional_annotations, region_annotations, size, svtype, decipher, depth, alt_count, control_frequency
        secondary_terms = False

        # check if any of the primary criteria was specified in the query
        for term in PRIMARY_CRITERIA:
            if query.get(term):
                primary_terms = True

        # check if any of the secondary criteria was specified in the query:
        for term in SECONDARY_CRITERIA:
            if query.get(term):
                secondary_terms = True

        if primary_terms is True:
            clinsign_filter = self.clinsig_query(query, mongo_query)

        # Secondary, excluding filter criteria will hide variants in general,
        # but can be overridden by an including, major filter criteria
        # such as a Pathogenic ClinSig.
        if secondary_terms is True:
            secondary_filter = self.secondary_query(query, mongo_query)

            # If there are no primary criteria given, all secondary criteria are added as a
            # top level '$and' to the query.
            if primary_terms is False:
                if gene_query:
                    mongo_query['$and'] = [ {'$or': gene_query}, {'$and': secondary_filter}]
                else:
                    mongo_query['$and'] = secondary_filter

            # If there is only one primary criterion given without any secondary, it will also be
            # added as a top level '$and'.
            # Otherwise, primary criteria are added as a high level '$or' and all secondary criteria
            # are joined together with them as a single lower level '$and'.
            if primary_terms is True: # clinsig is specified

                # Given a request to always return confident clinical variants,
                # add the clnsig query as a major criteria, but only
                # trust clnsig entries with trusted revstat levels.
                if query.get('clinsig_confident_always_returned') == True:
                    if gene_query:
                        mongo_query['$and'] = [
                            {'$or': gene_query},
                            {
                                '$or': [
                                    {'$and': secondary_filter}, clinsign_filter
                                ]
                            }
                        ]
                    else:
                        mongo_query['$or'] = [ {'$and': secondary_filter}, clinsign_filter ]
                else: # clisig terms are provided but no need for trusted revstat levels
                    secondary_filter.append(clinsign_filter)
                    if gene_query:
                        mongo_query['$and'] = [ {'$or': gene_query}, {'$and': secondary_filter}]
                    else:
                        mongo_query['$and'] = secondary_filter

        elif primary_terms is True: # clisig is provided without secondary terms query
            # use implicit and
            mongo_query['clnsig'] = clinsign_filter['clnsig']
            if gene_query:
                mongo_query['$and'] = [{ '$or': gene_query }]

        elif gene_query: # no primary or secondary filters provided
            mongo_query['$and'] = [{ '$or': gene_query }]

        LOG.info("mongo query: %s", mongo_query)

        return mongo_query
Build a mongo query

        These are the different query options:
            {
                'genetic_models': list,
                'chrom': str,
                'thousand_genomes_frequency': float,
                'exac_frequency': float,
                'clingen_ngi': int,
                'cadd_score': float,
                'cadd_inclusive": boolean,
                'genetic_models': list(str),
                'hgnc_symbols': list,
                'region_annotations': list,
                'functional_annotations': list,
                'clinsig': list,
                'clinsig_confident_always_returned': boolean,
                'variant_type': str(('research', 'clinical')),
                'chrom': str,
                'start': int,
                'end': int,
                'svtype': list,
                'size': int,
                'size_shorter': boolean,
                'gene_panels': list(str),
                'mvl_tag": boolean,
                'decipher": boolean,
            }

        Arguments:
            case_id(str)
            query(dict): a dictionary of query filters specified by the users
            variant_ids(list(str)): A list of md5 variant ids

        Returns:
            mongo_query : A dictionary in the mongo query format