Skip to content

Commit 8307952

Browse files
committed
Add BCO Score to model.
Also added functions and methods for BCO Score. Updates to the BCO admin panel. Updates to the `test_data.json` and `local_data.json` Fix # 310 Changes to be committed: modified: authentication/migrations/0001_initial.py modified: biocompute/admin.py modified: biocompute/apis.py modified: biocompute/migrations/0001_initial.py modified: biocompute/models.py modified: biocompute/services.py new file: config/bco_scores.py modified: config/fixtures/local_data.json modified: tests/fixtures/test_data.json
1 parent 8ee1039 commit 8307952

File tree

9 files changed

+838
-267
lines changed

9 files changed

+838
-267
lines changed

authentication/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 3.2.13 on 2024-03-14 13:52
1+
# Generated by Django 3.2.13 on 2024-04-11 21:18
22

33
from django.conf import settings
44
from django.db import migrations, models

biocompute/admin.py

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,44 @@
1-
"""BioCompute Object Admin Pannel
2-
"""
3-
41
from django.contrib import admin
5-
from biocompute.models import Bco
2+
from django.utils.html import format_html_join
3+
from django.utils.safestring import mark_safe
4+
from .models import Bco, User, Prefix
5+
6+
class BcoAdmin(admin.ModelAdmin):
7+
list_display = (
8+
'object_id',
9+
'owner',
10+
'prefix',
11+
'state',
12+
'score',
13+
'last_update',
14+
'access_count',
15+
'display_authorized_users'
16+
)
17+
search_fields = ['object_id', 'owner__username', 'state']
18+
list_filter = ('state', 'last_update')
19+
fieldsets = (
20+
(None, {
21+
'fields': ('object_id', 'contents')
22+
}),
23+
('Permissions', {
24+
'fields': ('owner', 'authorized_users')
25+
}),
26+
('Details', {
27+
'fields': (
28+
'prefix',
29+
'state',
30+
'score',
31+
'last_update',
32+
'access_count'
33+
)
34+
}),
35+
)
36+
filter_horizontal = ('authorized_users',)
637

7-
# class BioComputeAdmin(admin.ModelAdmin):
8-
# list_display = ["", ""]
38+
def display_authorized_users(self, obj):
39+
"""Return a comma-separated list of authorized user names."""
40+
return mark_safe(", ".join(
41+
[user.username for user in obj.authorized_users.all()]))
42+
display_authorized_users.short_description = "Authorized Users"
943

10-
admin.site.register(Bco)
44+
admin.site.register(Bco, BcoAdmin)

biocompute/apis.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
retrieve_bco,
1616
user_can_modify_bco,
1717
user_can_publish_bco,
18-
object_id_deconstructor,
1918
)
2019
from config.services import (
2120
legacy_api_converter,
@@ -347,7 +346,7 @@ def post(self, request) -> Response:
347346
data = legacy_api_converter(request.data)
348347

349348
for index, object in enumerate(data):
350-
response_id = object.get("object_id", index)
349+
response_id = object["contents"].get("object_id", index)
351350
modify_permitted = user_can_modify_bco(response_id, requester)
352351

353352
if modify_permitted is None:
@@ -617,11 +616,12 @@ def post(self, request) -> Response:
617616
else:
618617
published_bco = publish_draft(bco_instance, requester, object)
619618
identifier=published_bco.object_id
619+
score = published_bco.score
620620
response_data.append(response_constructor(
621621
identifier=identifier,
622622
status = "SUCCESS",
623623
code= 201,
624-
message= f"BCO {identifier} has been published.",
624+
message= f"BCO {identifier} has been published and assigned {score} as a score.",
625625
))
626626
accepted_requests = True
627627

biocompute/migrations/0001_initial.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 3.2.13 on 2024-04-02 20:08
1+
# Generated by Django 3.2.13 on 2024-04-11 21:16
22

33
from django.conf import settings
44
from django.db import migrations, models
@@ -21,6 +21,7 @@ class Migration(migrations.Migration):
2121
('object_id', models.TextField(primary_key=True, serialize=False)),
2222
('contents', models.JSONField()),
2323
('state', models.CharField(choices=[('REFERENCED', 'referenced'), ('PUBLISHED', 'published'), ('DRAFT', 'draft'), ('DELETE', 'delete')], default='DRAFT', max_length=20)),
24+
('score', models.IntegerField(default=0)),
2425
('last_update', models.DateTimeField()),
2526
('access_count', models.IntegerField(default=0)),
2627
('authorized_users', models.ManyToManyField(blank=True, related_name='authorized_bcos', to=settings.AUTH_USER_MODEL)),

biocompute/models.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class Bco(models.Model):
3535
Prefix for the BCO
3636
state:str
3737
State of object. REFERENCED, PUBLISHED, DRAFT, and DELETE are currently accepted values.
38+
score:int
39+
Score assigned to BCO at the time of publishing.
3840
last_update: DateTime
3941
Date Time object for the last database change to this object
4042
access_count: Int
@@ -44,7 +46,11 @@ class Bco(models.Model):
4446

4547
object_id = models.TextField(primary_key=True)
4648
contents = models.JSONField()
47-
prefix = models.ForeignKey(Prefix, on_delete=models.CASCADE, to_field="prefix")
49+
prefix = models.ForeignKey(
50+
Prefix,
51+
on_delete=models.CASCADE,
52+
to_field="prefix"
53+
)
4854
owner = models.ForeignKey(
4955
User,
5056
to_field="username",
@@ -56,7 +62,12 @@ class Bco(models.Model):
5662
related_name="authorized_bcos",
5763
blank=True
5864
)
59-
state = models.CharField(max_length=20, choices=STATE_CHOICES, default="DRAFT")
65+
state = models.CharField(
66+
max_length=20,
67+
choices=STATE_CHOICES,
68+
default="DRAFT"
69+
)
70+
score = models.IntegerField(default=0)
6071
last_update = models.DateTimeField()
6172
access_count = models.IntegerField(default=0)
6273

biocompute/services.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,10 @@ def update(self, validated_data):
281281
)
282282
bco_instance.contents = validated_data['contents']
283283
bco_instance.last_update=timezone.now()
284-
bco_contents = deepcopy(bco_instance.contents)
284+
bco_contents = bco_instance.contents
285+
bco_contents["provenance_domain"]["modified"] = datetime_converter(
286+
timezone.now()
287+
)
285288
etag = generate_etag(bco_contents)
286289
bco_instance.contents['etag'] = etag
287290
bco_instance.save()
@@ -563,7 +566,8 @@ def publish_draft(bco_instance: Bco, user: User, object: dict):
563566
timezone.now()
564567
)
565568
contents["etag"] = generate_etag(contents)
566-
new_bco_instance.save()
569+
thingk = bco_score(bco_instance=new_bco_instance)
570+
import pdb; pdb.set_trace()
567571

568572
if object["delete_draft"] is True:
569573
deleted = delete_draft(bco_instance=bco_instance, user=user)
@@ -581,4 +585,20 @@ def delete_draft(bco_instance:Bco, user:User,):
581585
bco_instance.save()
582586

583587
return "deleted"
584-
588+
589+
def bco_score(bco_instance: Bco) -> Bco:
590+
"""BCO Score
591+
592+
Process and score BioCompute Objects (BCOs).
593+
594+
"""
595+
596+
contents = bco_instance.contents
597+
try:
598+
usability_domain_length = sum(len(s) for s in contents['usability_domain'])
599+
score = {"usability_domain_length": usability_domain_length}
600+
except TypeError:
601+
score = {"usability_domain_length": 0}
602+
bco_instance.score = usability_domain_length
603+
604+
return bco_instance

config/bco_scores.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import django
5+
import json
6+
7+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bcodb.settings")
8+
django.setup()
9+
10+
from django.db.models import F
11+
from django.db.models.functions import Length
12+
from biocompute.models import BCO
13+
14+
def main():
15+
"""
16+
Process and score BioCompute Objects (BCOs) based on the length of their usability_domain.
17+
18+
This function performs the following steps:
19+
1. Fetches all published BCOs from the database, specifically retrieving their object_id and
20+
the contents of their usability_domain.
21+
2. Calculates a 'score' for each BCO, which is the sum of the lengths of strings within the
22+
usability_domain field. If the usability_domain is not present or is invalid, a score of 0 is assigned.
23+
3. Sorts the BCOs in descending order based on their scores.
24+
4. Outputs the sorted list of BCOs, along with their scores, to a JSON file named 'bco_scores.json'.
25+
26+
The scoring and sorting help in identifying BCOs with more detailed and potentially more useful usability domains.
27+
"""
28+
# Fetching all BCOs with their id and usability_domain
29+
bcos = BCO.objects.filter(state='PUBLISHED').annotate(
30+
usability_domain=F('contents__usability_domain')
31+
).values('object_id', 'usability_domain')
32+
33+
bcos_list = list(bcos)
34+
35+
count = 0
36+
for bco in bcos_list:
37+
38+
try:
39+
usability_domain_length = sum(len(s) for s in bco['usability_domain'])
40+
count += 1
41+
bco['score'] = {
42+
"usability_domain_length": usability_domain_length
43+
}
44+
except TypeError:
45+
import pdb; pdb.set_trace()
46+
bco['score'] = {
47+
"usability_domain_length": 0
48+
}
49+
count += 1
50+
51+
sorted_list_of_dicts = sorted(bcos_list, key=lambda d: d['score']['usability_domain_length'], reverse=True)
52+
53+
with open('bco_scores.json', "w") as file:
54+
json.dump(sorted_list_of_dicts, file, indent=4)
55+
56+
if __name__ == "__main__":
57+
main()

0 commit comments

Comments
 (0)