diff --git a/yeastregulatorydb/regulatory_data/api/filters/BindingConcatenatedFilter.py b/yeastregulatorydb/regulatory_data/api/filters/BindingConcatenatedFilter.py index 4fd08e6..bfaae32 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/BindingConcatenatedFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/BindingConcatenatedFilter.py @@ -1,52 +1,20 @@ import django_filters -from django.db.models import Q -from ...models import Binding, BindingConcatenated, BindingManualQC +from yeastregulatorydb.regulatory_data.models import BindingConcatenated class BindingConcatenatedFilter(django_filters.rest_framework.FilterSet): id = django_filters.NumberFilter() - genomic_inserts = django_filters.NumberFilter() - mito_inserts = django_filters.NumberFilter() - plasmid_inserts = django_filters.NumberFilter() - notes = django_filters.CharFilter(lookup_expr="iexact") # Filter fields for related bindings - regulator = django_filters.NumberFilter(field_name="bindings__regulator") + regulator = django_filters.NumberFilter(field_name="regulator") regulator_locus_tag = django_filters.CharFilter( - field_name="bindings__regulator__genomicfeature__locus_tag", lookup_expr="iexact" + field_name="regulator__genomicfeature__locus_tag", lookup_expr="iexact" ) - regulator_symbol = django_filters.CharFilter( - field_name="bindings__regulator__genomicfeature__symbol", lookup_expr="iexact" - ) - batch = django_filters.CharFilter(field_name="bindings__batch", lookup_expr="iexact") - replicate = django_filters.NumberFilter(field_name="bindings__replicate") - source = django_filters.NumberFilter(field_name="bindings__source") - source_orig_id = django_filters.CharFilter(field_name="bindings__source_orig_id", lookup_expr="iexact") - strain = django_filters.CharFilter(field_name="bindings__strain", lookup_expr="iexact") - condition = django_filters.ChoiceFilter(field_name="bindings__condition", choices=Binding.CONDITION_CHOICES) - lab = django_filters.CharFilter(field_name="bindings__source__lab", lookup_expr="iexact") - assay = django_filters.CharFilter(field_name="bindings__source__assay", lookup_expr="iexact") - workflow = django_filters.CharFilter(field_name="bindings__source__workflow", lookup_expr="iexact") + regulator_symbol = django_filters.CharFilter(field_name="regulator__genomicfeature__symbol", lookup_expr="iexact") + source = django_filters.NumberFilter(field_name="source") + source_name = django_filters.CharFilter(field_name="source__name", lookup_expr="iexact") class Meta: model = BindingConcatenated - fields = [ - "id", - "genomic_inserts", - "mito_inserts", - "plasmid_inserts", - "notes", - "regulator", - "regulator_locus_tag", - "regulator_symbol", - "batch", - "replicate", - "source", - "condition", - "source_orig_id", - "strain", - "lab", - "assay", - "workflow", - ] + fields = ["id", "regulator", "regulator_locus_tag", "regulator_symbol", "source", "source_name"] diff --git a/yeastregulatorydb/regulatory_data/api/filters/BindingFilter.py b/yeastregulatorydb/regulatory_data/api/filters/BindingFilter.py index 9143971..d84c685 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/BindingFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/BindingFilter.py @@ -22,7 +22,7 @@ class BindingFilter(django_filters.rest_framework.FilterSet): assay = django_filters.CharFilter(field_name="source__assay", lookup_expr="iexact") workflow = django_filters.CharFilter(field_name="source__workflow", lookup_expr="iexact") data_usable = django_filters.ChoiceFilter( - field_name="bindingmanualqc__data_usable", choices=BindingManualQC.MANUAL_QC_CHOICES + field_name="bindingmanualqc__data_usable", choices=BindingManualQC.MANUAL_QC_CHOICES, label="Data Usable" ) # pylint: disable=R0801 diff --git a/yeastregulatorydb/regulatory_data/api/filters/BindingManualQCFilter.py b/yeastregulatorydb/regulatory_data/api/filters/BindingManualQCFilter.py index 183222a..a9163a2 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/BindingManualQCFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/BindingManualQCFilter.py @@ -1,25 +1,48 @@ import django_filters +from django.db.models import Q from ...models.BindingManualQC import BindingManualQC class BindingManualQCFilter(django_filters.rest_framework.FilterSet): id = django_filters.NumberFilter() - single_binding = django_filters.NumberFilter() - composite_binding = django_filters.NumberFilter() - best_datatype = django_filters.ChoiceFilter(choices=BindingManualQC.MANUAL_QC_CHOICES) - data_usable = django_filters.ChoiceFilter(choices=BindingManualQC.MANUAL_QC_CHOICES) - passing_replicate = django_filters.ChoiceFilter(choices=BindingManualQC.MANUAL_QC_CHOICES) - rank_recall = django_filters.ChoiceFilter(choices=BindingManualQC.MANUAL_QC_CHOICES) - regulator = django_filters.NumberFilter(field_name="binding__regulator") + single_binding = django_filters.NumberFilter(label="Single Binding ID", help_text="ID of the single binding") + composite_binding = django_filters.NumberFilter( + label="Composite Binding ID", help_text="ID of the composite binding" + ) + best_datatype = django_filters.ChoiceFilter( + choices=BindingManualQC.MANUAL_QC_CHOICES, label="Best Datatype", help_text="Best datatype for the binding" + ) + data_usable = django_filters.ChoiceFilter( + choices=BindingManualQC.MANUAL_QC_CHOICES, label="Data Usable", help_text="Data usable for the binding" + ) + passing_replicate = django_filters.ChoiceFilter( + choices=BindingManualQC.MANUAL_QC_CHOICES, + label="Passing Replicate", + help_text="Passing replicate for the binding", + ) + rank_recall = django_filters.ChoiceFilter( + choices=BindingManualQC.MANUAL_QC_CHOICES, label="Rank Recall", help_text="Rank recall for the binding" + ) + regulator = django_filters.NumberFilter(method="filter_regulator", label="Regulator ID", help_text="Regulator ID") regulator_locus_tag = django_filters.CharFilter( - field_name="binding__regulator__genomicfeature__locus_tag", lookup_expr="iexact" + method="filter_regulator_locus_tag", + lookup_expr="iexact", + label="Regulator locus tag", + help_text="Regulator locus tag", ) regulator_symbol = django_filters.CharFilter( - field_name="binding__regulator__genomicfeature__symbol", lookup_expr="iexact" + method="filter_regulator_symbol", lookup_expr="iexact", label="Regulator symbol", help_text="Regulator symbol" + ) + batch = django_filters.CharFilter( + method="filter_batch", lookup_expr="iexact", label="Binding Batch", help_text="Binding batch" + ) + source = django_filters.CharFilter( + method="filter_source", lookup_expr="iexact", label="Data Source ID", help_text="Data Source ID" + ) + source_name = django_filters.CharFilter( + method="filter_source", lookup_expr="iexact", label="Data Source name", help_text="Data Source name" ) - batch = django_filters.CharFilter(field_name="binding__batch", lookup_expr="iexact") - source = django_filters.CharFilter(field_name="binding__source", lookup_expr="iexact") class Meta: model = BindingManualQC @@ -30,9 +53,35 @@ class Meta: "best_datatype", "data_usable", "passing_replicate", + "rank_recall", "regulator", "regulator_locus_tag", "regulator_symbol", "batch", "source", + "source_name", ] + + def filter_binding(self, queryset, name, value): + return queryset.filter( + Q(single_binding__isnull=False, **{f"single_binding__{name}": value}) + | Q(composite_binding__isnull=False, **{f"composite_binding__{name}": value}) + ) + + def filter_regulator(self, queryset, name, value): + return self.filter_binding(queryset, "regulator", value) + + def filter_regulator_locus_tag(self, queryset, name, value): + return self.filter_binding(queryset, "regulator__genomicfeature__locus_tag", value) + + def filter_regulator_symbol(self, queryset, name, value): + return self.filter_binding(queryset, "regulator__genomicfeature__symbol", value) + + def filter_batch(self, queryset, name, value): + return self.filter_binding(queryset, "batch", value) + + def filter_source(self, queryset, name, value): + return self.filter_binding(queryset, "source", value) + + def filter_source(self, queryset, name, value): + return self.filter_binding(queryset, "source_name", value) diff --git a/yeastregulatorydb/regulatory_data/api/filters/DataSourceFilter.py b/yeastregulatorydb/regulatory_data/api/filters/DataSourceFilter.py index 09b30cc..ca8b5d0 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/DataSourceFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/DataSourceFilter.py @@ -5,11 +5,19 @@ class DataSourceFilter(django_filters.rest_framework.FilterSet): id = django_filters.NumberFilter() - fileformat_id = django_filters.NumberFilter() - fileformat = django_filters.CharFilter(field_name="fileformat__fileformat", lookup_expr="iexact") - lab = django_filters.CharFilter(lookup_expr="iexact") - assay = django_filters.CharFilter(lookup_expr="iexact") - workflow = django_filters.CharFilter(lookup_expr="iexact") + fileformat_id = django_filters.NumberFilter(label="File Format ID", help_text="ID of the file format") + fileformat = django_filters.CharFilter( + field_name="fileformat__fileformat", lookup_expr="iexact", label="File Format", help_text="File format" + ) + lab = django_filters.CharFilter(lookup_expr="iexact", label="Lab", help_text="Lab which generated the data") + assay = django_filters.CharFilter( + lookup_expr="iexact", + label="Assay", + help_text="Assay used to generate the data, eg 'callingcards' or 'chipexo'", + ) + workflow = django_filters.CharFilter( + lookup_expr="iexact", label="Workflow", help_text="Workflow used to generate data" + ) class Meta: model = DataSource diff --git a/yeastregulatorydb/regulatory_data/api/filters/ExpressionFilter.py b/yeastregulatorydb/regulatory_data/api/filters/ExpressionFilter.py index c9dc97b..9994de8 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/ExpressionFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/ExpressionFilter.py @@ -13,21 +13,47 @@ class ExpressionFilter(django_filters.rest_framework.FilterSet): # pylint: disable=R0801 id = django_filters.NumberFilter() - regulator = django_filters.NumberFilter() - regulator_locus_tag = ListCharFilter(field_name="regulator__genomicfeature__locus_tag", lookup_expr="iexact") - regulator_symbol = ListCharFilter(field_name="regulator__genomicfeature__symbol", lookup_expr="iexact") - batch = django_filters.CharFilter(field_name="batch", lookup_expr="iexact") + regulator = django_filters.NumberFilter(help_text="Regulator Record ID") + regulator_locus_tag = ListCharFilter( + field_name="regulator__genomicfeature__locus_tag", + lookup_expr="iexact", + label="Regulator Locus Tag", + help_text="Comma separated list of locus tags", + ) + regulator_symbol = ListCharFilter( + field_name="regulator__genomicfeature__symbol", + lookup_expr="iexact", + label="Regulator Symbol", + help_text="Comma separated list of symbols", + ) + batch = django_filters.CharFilter(field_name="batch", lookup_expr="iexact", help_text="Expression Batch string") # pylint: enable=R0801 - replicate = django_filters.NumberFilter() - control = django_filters.CharFilter(lookup_expr="iexact") - mechanism = django_filters.CharFilter(lookup_expr="iexact") - restriction = django_filters.CharFilter(lookup_expr="iexact") - time = django_filters.NumberFilter(field_name="time") - source = django_filters.NumberFilter() - source_time = django_filters.CharFilter(method="filter_source_time") - lab = django_filters.CharFilter(field_name="source__lab", lookup_expr="iexact") - assay = django_filters.CharFilter(field_name="source__assay", lookup_expr="iexact") - workflow = django_filters.CharFilter(field_name="source__workflow", lookup_expr="iexact") + replicate = django_filters.NumberFilter(label="Replicate Number", help_text="Replicate number") + control = django_filters.CharFilter( + lookup_expr="iexact", label="Experiment control condition", help_text="Control condition" + ) + mechanism = django_filters.CharFilter( + lookup_expr="iexact", label="Regulatory Mechanism", help_text="Regulatory Mechanism (McIsaac only)" + ) + restriction = django_filters.CharFilter( + lookup_expr="iexact", label="Restriction enzyme", help_text="Regulatory enzyme (McIsaac only)" + ) + time = django_filters.NumberFilter(field_name="time", label="Time Point", help_text="Time point (McIsaac only)") + source = django_filters.NumberFilter(label="Source Record ID", help_text="Source Record ID") + source_time = django_filters.CharFilter( + method="filter_source_time", + label="Source/Time", + help_text="Comma separated tuples of source/time pairs separated by semi-colons", + ) + lab = django_filters.CharFilter( + field_name="source__lab", lookup_expr="iexact", label="Lab Name", help_text="Lab Name" + ) + assay = django_filters.CharFilter( + field_name="source__assay", lookup_expr="iexact", label="Assay Name", help_text="Assay Name" + ) + workflow = django_filters.CharFilter( + field_name="source__workflow", lookup_expr="iexact", label="Workflow Name", help_text="Workflow Name" + ) class Meta: model = Expression diff --git a/yeastregulatorydb/regulatory_data/api/filters/ExpressionManualQCFilter.py b/yeastregulatorydb/regulatory_data/api/filters/ExpressionManualQCFilter.py index 9a33b98..dfc0a11 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/ExpressionManualQCFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/ExpressionManualQCFilter.py @@ -5,24 +5,44 @@ class ExpressionManualQCFilter(django_filters.rest_framework.FilterSet): id = django_filters.NumberFilter() - expression = django_filters.NumberFilter() - strain_verified = django_filters.ChoiceFilter(choices=[("yes", "yes"), ("no", "no"), ("unverified", "unverified")]) + expression = django_filters.NumberFilter(label="Expression ID", help_text="ID of the expression") + strain_verified = django_filters.ChoiceFilter( + choices=[("yes", "yes"), ("no", "no"), ("unverified", "unverified")], + label="Strain Verified", + help_text="Strain verified status", + ) regulator_locus_tag = django_filters.CharFilter( - field_name="expression__regulator__genomicfeature__locus_tag", lookup_expr="iexact" + field_name="expression__regulator__genomicfeature__locus_tag", + lookup_expr="iexact", + label="Regulator locus tag", + help_text="Regulator locus tag", ) regulator_symbol = django_filters.CharFilter( - field_name="expression__regulator__genomicfeature__symbol", lookup_expr="iexact" + field_name="expression__regulator__genomicfeature__symbol", + lookup_expr="iexact", + label="Regulator symbol", + help_text="Regulator symbol", + ) + time = django_filters.NumberFilter(field_name="expression__time", label="Time", help_text="Time (McIsaac only)") + source = django_filters.NumberFilter(field_name="expression__source__id", label="Source ID", help_text="Source ID") + lab = django_filters.CharFilter( + field_name="expression__source__lab", + lookup_expr="iexact", + label="Lab Name", + help_text="Lab which generated the data", + ) + assay = django_filters.CharFilter( + field_name="expression__source__assay", + lookup_expr="iexact", + label="Assay Name", + help_text="Assay used to generate the data, eg 'callingcards'", + ) + workflow = django_filters.CharFilter( + field_name="expression__source__workflow", + lookup_expr="iexact", + label="Workflow Name", + help_text="Workflow used to generate data", ) - batch = django_filters.CharFilter(field_name="expression__batch", lookup_expr="iexact") - replicate = django_filters.NumberFilter(field_name="expression__replicate") - control = django_filters.CharFilter(field_name="expression__control", lookup_expr="iexact") - mechanism = django_filters.CharFilter(field_name="expression__mechanism", lookup_expr="iexact") - restriction = django_filters.CharFilter(field_name="expression__restriction", lookup_expr="iexact") - time = django_filters.NumberFilter(field_name="expression__time") - source = django_filters.NumberFilter(field_name="expression__source__id") - lab = django_filters.CharFilter(field_name="expression__source__lab", lookup_expr="iexact") - assay = django_filters.CharFilter(field_name="expression__source__assay", lookup_expr="iexact") - workflow = django_filters.CharFilter(field_name="expression__source__workflow", lookup_expr="iexact") # pylint: disable=R0801 class Meta: @@ -33,11 +53,6 @@ class Meta: "strain_verified", "regulator_locus_tag", "regulator_symbol", - "batch", - "replicate", - "control", - "mechanism", - "restriction", "time", "source", "lab", diff --git a/yeastregulatorydb/regulatory_data/api/filters/GenomicFeatureFilter.py b/yeastregulatorydb/regulatory_data/api/filters/GenomicFeatureFilter.py index 8d3ecc4..b414771 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/GenomicFeatureFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/GenomicFeatureFilter.py @@ -5,15 +5,35 @@ class GenomicFeatureFilter(django_filters.rest_framework.FilterSet): id = django_filters.NumberFilter() - chr = django_filters.CharFilter(field_name="chr__ucsc") - start = django_filters.NumberFilter() - end = django_filters.NumberFilter() - strand = django_filters.CharFilter(lookup_expr="exact") - type = django_filters.CharFilter(lookup_expr="iexact") - locus_tag = django_filters.CharFilter(lookup_expr="iexact") - symbol = django_filters.CharFilter(lookup_expr="iexact") - source = django_filters.CharFilter(lookup_expr="iexact") - alias = django_filters.CharFilter(lookup_expr="iexact") + chr = django_filters.CharFilter( + field_name="chr__ucsc", lookup_expr="exact", label="Chromosome", help_text="Chromosome" + ) + start = django_filters.RangeFilter( + field_name="start", + label="Start coordinate", + help_text="A range describing the start position(s) of the feature", + ) + end = django_filters.RangeFilter( + field_name="end", label="End coordinate", help_text="A range describing the end position(s) of the feature" + ) + strand = django_filters.CharFilter(lookup_expr="exact", label="Feature strand", help_text="Feature strand") + type = django_filters.CharFilter( + lookup_expr="iexact", label="Feature type", help_text="Feature type, eg `gene', `CDS', `tRNA', etc" + ) + locus_tag = django_filters.CharFilter( + lookup_expr="iexact", label="Locus tag", help_text="The systematic ID from SGD" + ) + symbol = django_filters.CharFilter( + lookup_expr="iexact", label="Feature symbol", help_text="The common name of the feature from SGD" + ) + source = django_filters.CharFilter( + lookup_expr="iexact", label="Feature source", help_text="Source of the annotation" + ) + alias = django_filters.CharFilter( + lookup_expr="iexact", + label="Feature alias", + help_text="If there are aliases for the common name of the feature, they are listed in this field", + ) note = django_filters.CharFilter(lookup_expr="iexact") class Meta: diff --git a/yeastregulatorydb/regulatory_data/api/filters/PromoterSetSigFilter.py b/yeastregulatorydb/regulatory_data/api/filters/PromoterSetSigFilter.py index 88005a8..21a3798 100644 --- a/yeastregulatorydb/regulatory_data/api/filters/PromoterSetSigFilter.py +++ b/yeastregulatorydb/regulatory_data/api/filters/PromoterSetSigFilter.py @@ -1,35 +1,69 @@ import django_filters +from django.db.models import Q -from ...models import PromoterSetSig -from ...models.BindingManualQC import BindingManualQC -from ...models.PromoterSetSig import PromoterSetSig +from ...models import BindingManualQC, PromoterSetSig class PromoterSetSigFilter(django_filters.rest_framework.FilterSet): - id = django_filters.NumberFilter() - single_binding = django_filters.NumberFilter() - composite_binding = django_filters.NumberFilter() - promoter = django_filters.NumberFilter() - promoter_name = django_filters.CharFilter(field_name="promoter__name", lookup_expr="iexact") - background = django_filters.NumberFilter() - background_name = django_filters.CharFilter(field_name="background__name", lookup_expr="iexact") + id = django_filters.NumberFilter(label="Promoter Set Signature ID", help_text="ID of the promoter set signature") + single_binding = django_filters.NumberFilter( + label="Single Binding ID", + help_text="All binding replicates for single binding data sets have a single binding ID", + ) + composite_binding = django_filters.NumberFilter( + label="Composite Binding ID", help_text="Aggregated callingcards replicate sets have a composite binding ID" + ) + promoter = django_filters.NumberFilter(label="PromoterSet ID", help_text="ID of the promoter set") + promoter_name = django_filters.CharFilter( + field_name="promoter__name", lookup_expr="iexact", label="Promoter Name", help_text="Name of the promoter set" + ) + background = django_filters.NumberFilter(label="Background ID", help_text="ID of the background") + background_name = django_filters.CharFilter( + field_name="background__name", + lookup_expr="iexact", + label="Background Name", + help_text="Name of the background", + ) regulator_locus_tag = django_filters.CharFilter( - field_name="single_binding__regulator__genomicfeature__locus_tag", lookup_expr="iexact" + method="filter_regulator_locus_tag", + lookup_expr="iexact", + label="Regulator locus tag", + help_text="Regulator locus tag", ) regulator_symbol = django_filters.CharFilter( - field_name="single_binding__regulator__genomicfeature__symbol", lookup_expr="iexact" - ) - batch = django_filters.CharFilter(field_name="single_binding__batch", lookup_expr="iexact") - replicate = django_filters.NumberFilter(field_name="single_binding__replicate") - source = django_filters.NumberFilter(field_name="single_binding__source") - lab = django_filters.CharFilter(field_name="single_binding__source__lab", lookup_expr="iexact") - assay = django_filters.CharFilter(field_name="single_binding__source__assay", lookup_expr="iexact") - workflow = django_filters.CharFilter(field_name="single_binding__source__workflow", lookup_expr="iexact") + method="filter_regulator_symbol", lookup_expr="iexact", label="Regulator symbol", help_text="Regulator symbol" + ) + batch = django_filters.CharFilter( + method="filter_batch", lookup_expr="iexact", label="Binding Batch", help_text="Binding batch" + ) + source = django_filters.NumberFilter(method="filter_source", label="Data Source ID", help_text="Data Source ID") + lab = django_filters.CharFilter( + method="filter_lab", + lookup_expr="iexact", + label="Binding Data Lab Name", + help_text="Lab name which generated the binding data", + ) + assay = django_filters.CharFilter( + method="filter_assay", lookup_expr="iexact", label="Binding Data Assay Name", help_text="Binding assay name" + ) + workflow = django_filters.CharFilter( + method="filter_workflow", + lookup_expr="iexact", + label="Binding Data Workflow", + help_text="Binding workflow name", + ) data_usable = django_filters.ChoiceFilter( - field_name="single_binding__bindingmanualqc__data_usable", choices=BindingManualQC.MANUAL_QC_CHOICES + method="filter_data_usable", + choices=BindingManualQC.MANUAL_QC_CHOICES, + label="Binding Data Usable", + help_text="Binding data usable status", + ) + aggregated = django_filters.BooleanFilter( + method="filter_aggregated", + label="Aggregated", + help_text="Filter by aggregated (composite_binding is not null)", ) - # pylint: disable=R0801 class Meta: model = PromoterSetSig fields = [ @@ -42,11 +76,49 @@ class Meta: "background_name", "regulator_locus_tag", "regulator_symbol", - "batch", - "replicate", "source", "lab", "assay", "workflow", + "data_usable", + "aggregated", ] - # pylint: enable=R0801 + + def filter_binding(self, queryset, name, value): + return queryset.filter( + Q(single_binding__isnull=False, **{f"single_binding__{name}": value}) + | Q(composite_binding__isnull=False, **{f"composite_binding__{name}": value}) + ) + + def filter_single_binding(self, queryset, name, value): + return queryset.filter(**{f"single_binding__{name}": value}) + + def filter_regulator_locus_tag(self, queryset, name, value): + return self.filter_binding(queryset, "regulator__genomicfeature__locus_tag", value) + + def filter_regulator_symbol(self, queryset, name, value): + return self.filter_binding(queryset, "regulator__genomicfeature__symbol", value) + + def filter_batch(self, queryset, name, value): + return self.filter_single_binding(queryset, "batch", value) + + def filter_source(self, queryset, name, value): + return self.filter_binding(queryset, "source", value) + + def filter_lab(self, queryset, name, value): + return self.filter_binding(queryset, "source__lab", value) + + def filter_assay(self, queryset, name, value): + return self.filter_binding(queryset, "source__assay", value) + + def filter_workflow(self, queryset, name, value): + return self.filter_binding(queryset, "source__workflow", value) + + def filter_data_usable(self, queryset, name, value): + return self.filter_binding(queryset, "bindingmanualqc__data_usable", value) + + def filter_aggregated(self, queryset, name, value): + if value: + return queryset.filter(composite_binding__isnull=False) + else: + return queryset.filter(composite_binding__isnull=True) diff --git a/yeastregulatorydb/regulatory_data/api/serializers/PromoterSetSigSerializer.py b/yeastregulatorydb/regulatory_data/api/serializers/PromoterSetSigSerializer.py index a8aaab7..d16e31c 100644 --- a/yeastregulatorydb/regulatory_data/api/serializers/PromoterSetSigSerializer.py +++ b/yeastregulatorydb/regulatory_data/api/serializers/PromoterSetSigSerializer.py @@ -38,12 +38,41 @@ def validate(self, data): def to_representation(self, instance): ret = super().to_representation(instance) - ret["source"] = self.get_source(instance) - ret["regulator_symbol"] = self.get_regulator_symbol(instance) - ret["regulator_locus_tag"] = self.get_regulator_locus_tag(instance) + + if instance.single_binding: + single_binding = instance.single_binding + ret["source"] = single_binding.source.name + ret["regulator_symbol"] = single_binding.regulator.genomicfeature.symbol + ret["regulator_locus_tag"] = single_binding.regulator.genomicfeature.locus_tag + qc_set = list(single_binding.bindingmanualqc_set.all()) + ret["rank_recall"] = qc_set[0].rank_recall if qc_set else None + ret["data_usable"] = qc_set[0].data_usable if qc_set else None + elif instance.composite_binding: + composite_binding = instance.composite_binding + bindings = list(composite_binding.bindings.all()) + if bindings: + first_binding = bindings[0] + ret["source"] = first_binding.source.name + ret["regulator_symbol"] = first_binding.regulator.genomicfeature.symbol + ret["regulator_locus_tag"] = first_binding.regulator.genomicfeature.locus_tag + qc_set = list(first_binding.bindingmanualqc_set.all()) + ret["rank_recall"] = qc_set[0].rank_recall if qc_set else None + ret["data_usable"] = qc_set[0].data_usable if qc_set else None + else: + ret["source"] = None + ret["regulator_symbol"] = None + ret["regulator_locus_tag"] = None + ret["rank_recall"] = None + ret["data_usable"] = None + else: + ret["source"] = None + ret["regulator_symbol"] = None + ret["regulator_locus_tag"] = None + ret["rank_recall"] = None + ret["data_usable"] = None + ret["background_name"] = instance.background.name if instance.background else None - ret["rank_recall"] = self.get_rank_recall(instance) - ret["data_usable"] = self.get_data_usable(instance) + return ret def get_source(self, instance): diff --git a/yeastregulatorydb/regulatory_data/api/views/PromoterSetSigViewSet.py b/yeastregulatorydb/regulatory_data/api/views/PromoterSetSigViewSet.py index 3d71dde..cdd0ed5 100644 --- a/yeastregulatorydb/regulatory_data/api/views/PromoterSetSigViewSet.py +++ b/yeastregulatorydb/regulatory_data/api/views/PromoterSetSigViewSet.py @@ -77,6 +77,7 @@ class PromoterSetSigViewSet( "single_binding__regulator", "single_binding__regulator__genomicfeature", "single_binding__source", + "composite_binding", "composite_binding__regulator", "composite_binding__regulator__genomicfeature", "composite_binding__source", @@ -85,9 +86,12 @@ class PromoterSetSigViewSet( "fileformat", ) .prefetch_related( - "composite_binding__bindings", "single_binding__bindingmanualqc_set", + "composite_binding__bindings", "composite_binding__bindings__bindingmanualqc_set", + "composite_binding__bindings__source", + "composite_binding__bindings__regulator", + "composite_binding__bindings__regulator__genomicfeature", ) .all() .order_by("id") diff --git a/yeastregulatorydb/regulatory_data/tests/test_filters.py b/yeastregulatorydb/regulatory_data/tests/test_filters.py index ee30fdf..4bcedb6 100644 --- a/yeastregulatorydb/regulatory_data/tests/test_filters.py +++ b/yeastregulatorydb/regulatory_data/tests/test_filters.py @@ -367,11 +367,6 @@ def test_expression_manual_qc_filter(): {"strain_verified": manual_qc1.strain_verified}, {"regulator_locus_tag": regulator1.genomicfeature.locus_tag}, {"regulator_symbol": regulator1.genomicfeature.symbol}, - {"batch": expression1.batch}, - {"replicate": expression1.replicate}, - {"control": expression1.control}, - {"mechanism": expression1.mechanism}, - {"restriction": expression1.restriction}, {"time": expression1.time}, {"source": source1.id}, {"lab": source1.lab}, @@ -382,8 +377,8 @@ def test_expression_manual_qc_filter(): # Apply each filter and check if it returns the expected ExpressionManualQC instances for params in filter_params: f = ExpressionManualQCFilter(params, queryset=ExpressionManualQC.objects.all()) - assert manual_qc1 in f.qs - assert manual_qc2 not in f.qs + assert manual_qc1 in f.qs, params + assert manual_qc2 not in f.qs, params @pytest.mark.django_db @@ -437,8 +432,8 @@ def test_genomic_feature_filter(): # Define the filter parameters and their expected values filter_params = [ {"chr": "chr1"}, - {"start": 1}, - {"end": 100}, + {"start_min": 1, "start_max": 50}, # Test range filter for start + {"end_min": 50, "end_max": 150}, # Test range filter for end {"strand": "+"}, {"type": "type1"}, {"locus_tag": "tag1"}, @@ -451,8 +446,24 @@ def test_genomic_feature_filter(): # Apply each filter and check if it returns the expected GenomicFeature instances for params in filter_params: f = GenomicFeatureFilter(params, queryset=GenomicFeature.objects.all()) - assert genomic_feature1 in f.qs - assert genomic_feature2 not in f.qs + assert genomic_feature1 in f.qs, f"Failed for filter params: {params}" + assert genomic_feature2 not in f.qs, f"Failed for filter params: {params}" + + # Additional test cases for range filters + range_filter_params = [ + {"start_min": 0, "start_max": 200}, # Both genomic_feature1 and genomic_feature2 should be included + {"end_min": 1, "end_max": 150}, # Only genomic_feature1 should be included + ] + + # Apply each range filter and check the expected results + for params in range_filter_params: + f = GenomicFeatureFilter(params, queryset=GenomicFeature.objects.all()) + if "start_min" in params or "start_max" in params: + assert genomic_feature1 in f.qs, f"Failed for range filter params: {params}" + assert genomic_feature2 in f.qs, f"Failed for range filter params: {params}" if params["start_max"] == 200 else assert genomic_feature2 not in f.qs, f"Failed for range filter params: {params}" + if "end_min" in params or "end_max" in params: + assert genomic_feature1 in f.qs, f"Failed for range filter params: {params}" + assert genomic_feature2 not in f.qs, f"Failed for range filter params: {params}" @pytest.mark.django_db @@ -553,11 +564,6 @@ def test_promoter_set_sig_filter(): "expected": [promoter_set_sig1], "unexpected": [promoter_set_sig2, promoter_set_sig3], }, - { - "params": {"replicate": 1}, - "expected": [promoter_set_sig1], - "unexpected": [promoter_set_sig2, promoter_set_sig3], - }, { "params": {"source": datasource1.id}, "expected": [promoter_set_sig1, promoter_set_sig2],