Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usernames and full names in quality status API response (issue 1408) #725

Merged
merged 1 commit into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions viewer/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,26 @@ def annotated_qs(self):
'upload_version',
)
)


class SiteObservationQualityStatusQueryset(QuerySet):
def annotated_qs(self):
SiteObservationQualityStatus = apps.get_model(
"viewer",
"SiteObservationQualityStatus",
)
qs = SiteObservationQualityStatus.objects.annotate(
username=F("user__username"),
first_name=F("user__first_name"),
last_name=F("user__last_name"),
)

return qs


class SiteObservationQualityStatusDataManager(Manager):
def get_queryset(self):
return SiteObservationQualityStatusQueryset(self.model, using=self._db)

def annotated_qs(self):
return self.get_queryset().annotated_qs()
32 changes: 32 additions & 0 deletions viewer/migrations/0101_auto_20250226_1139.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 3.2.25 on 2025-02-26 11:39

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('viewer', '0100_auto_20250213_1039'),
]

operations = [
migrations.CreateModel(
name='RefinementStatusType',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('code', models.IntegerField(blank=True)),
('description', models.TextField(blank=True)),
('default_quality_status', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='viewer.qualitystatustype')),
],
),
migrations.AddField(
model_name='experiment',
name='refinement_outcome',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='viewer.refinementstatustype'),
),
migrations.AddConstraint(
model_name='refinementstatustype',
constraint=models.UniqueConstraint(fields=('code',), name='unique_refinement_code'),
),
]
41 changes: 41 additions & 0 deletions viewer/migrations/0102_auto_20250226_1146.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 3.2.25 on 2025-02-26 11:46

from django.db import migrations



refinement_status = (
(0, "All Datasets"),
(1, "Analysis Pending"),
(2, "PANDDA model"),
(3, "In Refinement"),
(4, "CompChem Ready"),
(5, "Deposition Ready"),
(6, "Deposited"),
(7, "Analysed & Rejected"),
)

class Migration(migrations.Migration):

dependencies = [
('viewer', '0101_auto_20250226_1139'),
]

def populate_refinements(apps, schema_editor):
RefinementStatusType = apps.get_model("viewer", "RefinementStatusType")
for code, description in refinement_status:
RefinementStatusType(
code=code,
description=description,
)



def depopulate_refinements(apps, schema_editor):
RefinementStatusType = apps.get_model("viewer", "RefinementStatusType")
RefinementStatusType.objects.all().delete()


operations = [
migrations.RunPython(populate_refinements, depopulate_refinements)
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.2.25 on 2025-02-26 12:04

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('viewer', '0102_auto_20250226_1146'),
]

operations = [
migrations.RemoveField(
model_name='refinementstatustype',
name='default_quality_status',
),
]
39 changes: 35 additions & 4 deletions viewer/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
QuatAssemblyDataManager,
SessionActionsDataManager,
SiteObservationDataManager,
SiteObservationQualityStatusDataManager,
SnapshotActionsDataManager,
SnapshotDataManager,
XtalformDataManager,
Expand Down Expand Up @@ -227,6 +228,32 @@ def get_download_path(self):
)


class QualityStatusType(models.Model):
status = models.TextField(primary_key=True)


class RefinementStatusType(models.Model):
code = models.IntegerField(blank=True)
description = models.TextField(blank=True)

class Meta:
constraints = [
models.UniqueConstraint(
fields=[
"code",
],
name="unique_refinement_code",
),
]

def __repr__(self) -> str:
return "<RefinementStatusType %r %r %r>" % (
self.id,
self.code,
self.description,
)


class Experiment(models.Model):
experiment_upload = models.ForeignKey(ExperimentUpload, on_delete=models.CASCADE)
code = models.TextField(null=True)
Expand Down Expand Up @@ -256,6 +283,11 @@ class Experiment(models.Model):
)
# need to set null=True due to the data saving order
xtalform = models.ForeignKey("Xtalform", null=True, on_delete=models.CASCADE)
refinement_outcome = models.ForeignKey(
RefinementStatusType,
on_delete=models.SET_NULL,
null=True,
)

objects = models.Manager()
filter_manager = ExperimentDataManager()
Expand Down Expand Up @@ -594,10 +626,6 @@ def get_ligand_mol_file(self):
return contents


class QualityStatusType(models.Model):
status = models.TextField(primary_key=True)


class SiteObservationQualityStatus(models.Model):
site_observation = models.ForeignKey(SiteObservation, on_delete=models.CASCADE)
status = models.ForeignKey(QualityStatusType, on_delete=models.CASCADE)
Expand All @@ -607,6 +635,9 @@ class SiteObservationQualityStatus(models.Model):
main_status = models.BooleanField(default=False)
comment = models.TextField()

objects = models.Manager()
filter_manager = SiteObservationQualityStatusDataManager()


class CompoundIdentifierType(models.Model):
name = models.TextField(primary_key=True)
Expand Down
7 changes: 7 additions & 0 deletions viewer/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1236,13 +1236,20 @@ class MetadataUploadSerializer(serializers.Serializer):


class SiteObservationQualityStatusSerializer(serializers.ModelSerializer):
username = serializers.CharField(read_only=True)
first_name = serializers.CharField(read_only=True)
last_name = serializers.CharField(read_only=True)

class Meta:
model = models.SiteObservationQualityStatus
fields = '__all__'
extra_kwargs = {
"auto_assigned": {"read_only": True},
"timestamp": {"read_only": True},
"user": {"read_only": True},
"username": {"read_only": True},
"first_name": {"read_only": True},
"last_name": {"read_only": True},
}

def create(self, validated_data):
Expand Down
22 changes: 9 additions & 13 deletions viewer/target_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import logging
import math
import os
import random

# import random
import shutil
import tarfile
from collections.abc import Callable
Expand Down Expand Up @@ -1533,17 +1534,17 @@ def process_site_observation(
"smiles": smiles,
}

index_data = {
"auto_build_score": random.random(),
}
# index_data = {
# "auto_build_score": random.random(),
# }

return ProcessedObject(
model_class=SiteObservation,
fields=fields,
defaults=defaults,
key=key,
versioned_key=v_key,
index_data=index_data,
index_data={},
)

def process_bundle(self):
Expand Down Expand Up @@ -2238,7 +2239,7 @@ def process_bundle(self):
if val.new:
self._assign_observation_quality_status(
val.instance,
val.index_data["auto_build_score"],
# val.index_data["auto_build_score"],
)

def import_compound_identifiers(self, alias_file_path):
Expand Down Expand Up @@ -2608,13 +2609,8 @@ def _get_final_path(self, path: str | None) -> Path | None:
# received invalid path
return None

def _assign_observation_quality_status(self, site_observation, score) -> None:
if score > 0.7:
status = QualityStatusType.objects.get(status="GOOD")
elif score <= 0.7 and score > 0.4:
status = QualityStatusType.objects.get(status="MEDIOCRE")
else:
status = QualityStatusType.objects.get(status="BAD")
def _assign_observation_quality_status(self, site_observation) -> None:
status = QualityStatusType.objects.get(status="NONE")

SiteObservationQualityStatus(
site_observation=site_observation,
Expand Down
2 changes: 1 addition & 1 deletion viewer/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2839,7 +2839,7 @@ class SiteObservationQualityStatusView(
mixins.UpdateModelMixin,
ISPyBSafeQuerySet,
):
queryset = models.SiteObservationQualityStatus.objects.all()
queryset = models.SiteObservationQualityStatus.filter_manager.annotated_qs()
serializer_class = serializers.SiteObservationQualityStatusSerializer
filterset_class = filters.SiteObservationQualityStatusFilter
filter_permissions = "site_observation__experiment__experiment_upload__project"