"""Genotype browser routes for browsing and listing variants in studies."""importitertoolsimportloggingfromtypingimportAny,castfromdae.utils.dae_utilsimportjoin_linefromdatasets_api.permissionsimport(handle_partial_permissions,user_has_permission,)fromdjango.http.responseimportFileResponse,StreamingHttpResponsefromquery_base.query_baseimportDatasetAccessRightsView,QueryBaseViewfromrest_frameworkimportstatusfromrest_framework.requestimportRequestfromrest_framework.responseimportResponsefromstudies.study_wrapperimportWDAEStudyfromutils.expand_gene_setimportexpand_gene_set,expand_gene_symsfromutils.loggerimportrequest_loggingfromutils.query_paramsimportparse_query_paramsfromutils.streaming_response_utilimportiterator_to_jsonlogger=logging.getLogger(__name__)
[docs]@request_logging(logger)defpost(self,request:Request,)->StreamingHttpResponse|FileResponse|Response:""" Query for variants from a dataset. Request: POST /genotype_browser/preview/variants HTTP/1.1 Host: example.com Content-Type: application/json Accept: text/event-stream { "datasetId": "iossifov_2014", "maxVariantsCount": 1000 } Response: HTTP/1.1 200 OK Vary: Accept Content-Type: text/event-stream [ [col1,col2,col3,col4.....] , [col1,col2,col3,col4.....] , ...... , [col1,col2,col3,col4.....] ] Status codes: 200: Successfully fetched variants 403: User has no permissions for dataset 400: Invalid request body 404: Dataset does not exist Request JSON parameters: datasetId (string): ID of the dataset to query. download (boolean): Change response type for easier download. genomicScores (json): Genomic score range filter. maxVariantsCount (integer): Maximum amount of variants to query. sources (list): List of name-source objects: columns to fetch. summaryVariantIds (list): List of summary variant IDs for filter. querySummary (boolean): True if should query only summary variants. uniqueFamilyVariants (boolean): Query for unique variants only. regions (list): List of regions as strings to filter with. presentInChild (json): Roles object to filter with. presentInParent (json): Roles object to filter with. inheritanceTypeFilter (list): Inheritance filtering. geneScores (list): Gene score range filter. genders (list): Gender filter. variantTypes (list): Filter by variant type. effectTypes (list): Filter by effect type. studyFilters (list): Filter by study ID (dataset only). personFilters (list): Filter with person filters. familyFilters (list): Filter with family filters. personIds (list): Filter by person IDs. familyTypes (list): Filter by family type. familyIds (list): Filter by family IDs. affectedStatus (list): Filter by affected status. tagIntersection (boolean): Change Family tags interesection mode selectedFamilyTags (list): Family tags to include deselectedFamilyTags (list): Family tags to exlude """# pylint: disable=too-many-brancheslogger.info("query v3 variants request: %s",str(request.data))data=cast(dict[str,Any],request.data)user=request.userifnotisinstance(data,dict):returnResponse(status=status.HTTP_400_BAD_REQUEST)if"queryData"indata:data=cast(dict[str,Any],parse_query_params(data))dataset_id=data.get("datasetId",None)ifdataset_idisNone:returnResponse(status=status.HTTP_400_BAD_REQUEST)ifnotuser_has_permission(self.instance_id,request.user,dataset_id):returnResponse(status=status.HTTP_403_FORBIDDEN)if"genomicScores"indata:scores=cast(list[dict[str,Any]],data["genomicScores"])forscoreinscores:ifscore.get("rangeStart")isNone \
andscore.get("rangeEnd")isNone \
andscore.get("values")isNone:returnResponse(status=status.HTTP_400_BAD_REQUEST)is_download=cast(bool,data.pop("download",False))if"maxVariantsCount"indata:max_variants=cast(int,data["maxVariantsCount"])else:ifis_download:max_variants=10000ifnotuser.is_anonymousand \
(user.is_stafforuser.has_unlimited_download):max_variants=Noneelse:max_variants=self.MAX_SHOWN_VARIANTS+1ifmax_variants==-1:# unlimited variants previewmax_variants=Nonedataset=self.gpf_instance.get_wdae_wrapper(dataset_id)ifdatasetisNone:returnResponse(status=status.HTTP_404_NOT_FOUND)ifdataset.is_phenotype:returnResponse(status=status.HTTP_400_BAD_REQUEST)ifnotdataset.genotype_data.is_remote:data=expand_gene_set(data)elif"geneSet"indata:gene_set=expand_gene_syms(data)data["geneSymbols"]=list(gene_set["syms"])deldata["geneSet"]if"sources"indata:sources=data.pop("sources")else:# TODO Handle summary variant preview and download sourcesstudy_config=dataset.genotype_data.configifis_download:cols=study_config["genotype_browser"]["download_columns"]else:cols=study_config["genotype_browser"]["preview_columns"]sources=WDAEStudy.get_columns_as_sources(dataset.genotype_data.config,cols,)ifnotisinstance(sources,list):returnResponse(status=status.HTTP_400_BAD_REQUEST)handle_partial_permissions(self.instance_id,user,dataset_id,data)response:FileResponse|StreamingHttpResponse|None=Noneresult=dataset.query_variants_wdae(data,sources,self.query_transformer,self.response_transformer,max_variants_count=max_variants,max_variants_message=is_download,)ifis_download:columns=[s.get("name",s["source"])forsinsources]result=map(join_line,itertools.chain([columns],filter(None,result)))# type: ignoreresponse=FileResponse(result,filename="variants.tsv",as_attachment=True,content_type="text/tsv",)response["Content-Disposition"]= \
"attachment; filename=variants.tsv"response["Expires"]="0"else:response=StreamingHttpResponse(iterator_to_json(result),status=status.HTTP_200_OK,content_type="text/event-stream",)response["Cache-Control"]="no-cache"returnresponse