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

Merged fixes for issues 1262, 1432, 1514, 1524 and 1552 #687

Merged
merged 30 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a9c9a67
feat: allow loading combi-soaks data
kaliif Oct 9, 2024
65db8fa
added ligand_key to compound
kaliif Oct 18, 2024
74e288b
Merge branch 'staging' into m2ms-1432-combi-soaks
kaliif Oct 18, 2024
4f887e8
stashing
kaliif Oct 18, 2024
690d15d
Merge branch 'staging' into m2ms-1262-compounds-auto
kaliif Oct 23, 2024
06a5b24
feat: loader processes and stores compounds_auto.csv
kaliif Oct 23, 2024
c2e600b
compound aliases to compound model
kaliif Oct 23, 2024
0769b5e
Preferred alias can be changed by user
kaliif Oct 23, 2024
88e45d9
fix: a bug in serializer showing full list
kaliif Oct 23, 2024
6f755f5
stashing
kaliif Oct 24, 2024
fc142bf
stashing
kaliif Oct 24, 2024
c9cd963
fix: ScoreDescriptor (not really) duplicates handled correctly
kaliif Oct 24, 2024
f086015
Merge branch 'staging' into m2ms-1432-combi-soaks
kaliif Oct 28, 2024
5394f5f
feat: new smiles fields to Compound model
kaliif Oct 28, 2024
72651fd
Merge branch 'staging' into m2ms-1524-rhs-upload-bug
kaliif Nov 4, 2024
5a2917a
fix: store all RHS uploaded files and return them on download
kaliif Nov 4, 2024
ad543c0
Merge branch 'm2ms-1262-compounds-auto' into stageprep
kaliif Nov 5, 2024
2da50b8
Merge branch 'm2ms-1432-combi-soaks' into stageprep
kaliif Nov 5, 2024
ca36ea5
Merge branch 'm2ms-1524-rhs-upload-bug' into stageprep
kaliif Nov 5, 2024
1a48e6e
Merge branch 'm2ms-1552-compound-visibility' into stageprep
kaliif Nov 5, 2024
bc189a3
Merged issues that were on hold. Autmatic migrations created.
kaliif Nov 5, 2024
69c7934
stashing
kaliif Nov 5, 2024
41d44ed
stashing
kaliif Nov 5, 2024
876495e
stashing
kaliif Nov 6, 2024
d43b68b
stashing
kaliif Nov 6, 2024
be40a2f
stashing
kaliif Nov 6, 2024
9485865
stashing
kaliif Nov 6, 2024
11b6f17
stashing
kaliif Nov 6, 2024
02daf2f
stashing
kaliif Nov 6, 2024
d91810d
fix: resolve migration failure when merging several diverging issues
kaliif Nov 6, 2024
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
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ services:
OIDC_RENEW_ID_TOKEN_EXPIRY_MINUTES: '210'
# Public target access strings?
# A comma-separated list of Project titles.
PUBLIC_TAS: lb18145-1
PUBLIC_TAS: ${PUBLIC_TAS:-lb18145-1}
# Squonk configuration
SQUONK2_VERIFY_CERTIFICATES: 'No'
SQUONK2_UNIT_BILLING_DAY: 3
Expand Down
68 changes: 41 additions & 27 deletions viewer/cset_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ def create_mol(self, inchi, target, name=None) -> Compound:
smiles=Chem.MolToSmiles(sanitized_mol),
inchi=inchi,
inchi_key=inchi_key,
current_identifier=name,
description=name,
)
# This is a new compound.
cpd.save()
Expand All @@ -317,27 +317,23 @@ def create_mol(self, inchi, target, name=None) -> Compound:

return cpd

def set_props(self, cpd, props, compound_set) -> List[ScoreDescription]:
def set_props(self, cpd, props, score_descriptions) -> List[ScoreDescription]:
if 'ref_mols' and 'ref_pdb' not in list(props.keys()):
raise Exception('ref_mols and ref_pdb not set!')
set_obj = ScoreDescription.objects.filter(computed_set=compound_set)
assert set_obj

set_props_list = [s.name for s in set_obj]
for key in list(props.keys()):
if key in set_props_list not in ['ref_mols', 'ref_pdb', 'original SMILES']:
if dataType(str(props[key])) == 'TEXT':
score_value = TextScoreValues()
else:
score_value = NumericalScoreValues()
score_value.score = ScoreDescription.objects.get(
computed_set=compound_set, name=key
)
score_value.value = props[key]
score_value.compound = cpd
score_value.save()

return set_obj
for sd in score_descriptions:
logger.debug('sd: %s', sd)
if dataType(str(props[sd.name])) == 'TEXT':
score_value = TextScoreValues()
else:
score_value = NumericalScoreValues()

score_value.value = props[sd.name]
score_value.compound = cpd
score_value.score = sd
score_value.save()

return score_descriptions

def set_mol(
self, mol, target, compound_set, filename, zfile=None, zfile_hashvals=None
Expand Down Expand Up @@ -550,15 +546,22 @@ def get_submission_info(self, description_mol) -> ComputedSetSubmitter:
)[0]

def process_mol(
self, mol, target, compound_set, filename, zfile=None, zfile_hashvals=None
self,
mol,
target,
compound_set,
filename,
score_descriptions,
zfile=None,
zfile_hashvals=None,
) -> List[ScoreDescription]:
cpd = self.set_mol(mol, target, compound_set, filename, zfile, zfile_hashvals)
other_props = mol.GetPropsAsDict()
return self.set_props(cpd, other_props, compound_set)
return self.set_props(cpd, other_props, score_descriptions)

def set_descriptions(
self, filename, computed_set: ComputedSet
) -> List[Chem.rdchem.Mol]:
) -> tuple[List[Chem.rdchem.Mol], List[ScoreDescription]]:
suppl = Chem.SDMolSupplier(str(filename))
description_mol = suppl[0]

Expand All @@ -577,6 +580,9 @@ def set_descriptions(
computed_set.save()

description_dict = description_mol.GetPropsAsDict()
# score descriptions for this upload, doesn't matter if
# created or existing
score_descriptions = []
for key in description_dict.keys():
if key in descriptions_needed and key not in [
'ref_mols',
Expand All @@ -585,13 +591,14 @@ def set_descriptions(
'Name',
'original SMILES',
]:
_ = ScoreDescription.objects.get_or_create(
description, _ = ScoreDescription.objects.get_or_create(
computed_set=computed_set,
name=key,
description=description_dict[key],
)
score_descriptions.append(description)

return mols
return mols, score_descriptions

def task(self) -> ComputedSet:
# Truncate submitted method (lower-case)?
Expand Down Expand Up @@ -673,7 +680,7 @@ def task(self) -> ComputedSet:
# This also sets the submitter and method URL properties of the computed set
# while also saving it.
sdf_filename = str(self.sdf_filename)
mols_to_process = self.set_descriptions(
mols_to_process, score_descriptions = self.set_descriptions(
filename=sdf_filename, computed_set=computed_set
)

Expand All @@ -688,14 +695,21 @@ def task(self) -> ComputedSet:
self.target_id,
computed_set,
sdf_filename,
score_descriptions,
self.zfile,
self.zfile_hashvals,
)

# move and save the compound set
new_filename = f'{settings.MEDIA_ROOT}{settings.COMPUTED_SET_MEDIA_DIRECTORY}/{computed_set.name}.sdf'
new_filename = (
Path(settings.MEDIA_ROOT)
.joinpath(settings.COMPUTED_SET_MEDIA_DIRECTORY)
.joinpath(
f'{computed_set.name}_upload_{computed_set.md_ordinal}_{Path(sdf_filename).name}'
)
)
os.rename(sdf_filename, new_filename)
computed_set.submitted_sdf = sdf_filename
computed_set.submitted_sdf = Path(sdf_filename).name
computed_set.written_sdf_filename = new_filename
computed_set.save()

Expand Down
18 changes: 18 additions & 0 deletions viewer/migrations/0065_compound_ligand_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.25 on 2024-10-18 09:46

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('viewer', '0064_auto_20240918_1256'),
]

operations = [
migrations.AddField(
model_name='compound',
name='ligand_name',
field=models.TextField(blank=True, default='LIG'),
),
]
49 changes: 49 additions & 0 deletions viewer/migrations/0073_historicalcomputedset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Generated by Django 3.2.25 on 2024-11-04 10:27

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import simple_history.models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('viewer', '0072_auto_20241010_1437'),
]

operations = [
migrations.CreateModel(
name='HistoricalComputedSet',
fields=[
('name', models.CharField(db_index=True, max_length=50)),
('submitted_sdf', models.TextField(help_text='The original SDF containing the ComputedSet', max_length=255)),
('written_sdf_filename', models.TextField(help_text='The written ComputedSet filename', max_length=1000, null=True)),
('spec_version', models.FloatField(help_text='The version of the SDF file format specification')),
('method_url', models.TextField(help_text='A url linking to a write-up of the methodology used to create the computed set', max_length=1000, null=True)),
('method', models.CharField(blank=True, help_text='The name of the algorithmic method used to generate the compounds (e.g. Fragmenstein)', max_length=50, null=True)),
('upload_date', models.DateField(blank=True, help_text='The date the set was uploaded', null=True)),
('md_ordinal', models.SmallIntegerField(blank=True, help_text='The ordinal distinguishing between uploads using the same method and date', null=True)),
('upload_task_id', models.CharField(help_text='The task ID of the upload Celery task', max_length=50, null=True)),
('upload_status', models.CharField(choices=[('PENDING', 'PENDING'), ('STARTED', 'STARTED'), ('SUCCESS', 'SUCCESS'), ('FAILURE', 'FAILURE'), ('RETRY', 'RETRY'), ('REVOKED', 'REVOKED')], help_text='Status of the upload. Only be updated at the end of the process', max_length=7, null=True)),
('upload_progress', models.DecimalField(decimal_places=2, help_text='Intended to be used as an indication of progress (0 to 100%)', max_digits=5, null=True)),
('upload_datetime', models.DateTimeField(help_text='The datetime the upload was completed', null=True)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('owner_user', models.ForeignKey(blank=True, db_constraint=False, default=1, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)),
('submitter', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='viewer.computedsetsubmitter')),
('target', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='viewer.target')),
],
options={
'verbose_name': 'historical computed set',
'verbose_name_plural': 'historical computed sets',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]
14 changes: 14 additions & 0 deletions viewer/migrations/0073_merge_20241018_0956.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.2.25 on 2024-10-18 09:56

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('viewer', '0065_compound_ligand_name'),
('viewer', '0072_auto_20241010_1437'),
]

operations = [
]
14 changes: 14 additions & 0 deletions viewer/migrations/0073_merge_20241028_1554.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.2.25 on 2024-10-28 15:54

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('viewer', '0065_compound_ligand_name'),
('viewer', '0072_auto_20241010_1437'),
]

operations = [
]
46 changes: 46 additions & 0 deletions viewer/migrations/0074_auto_20241018_1028.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generated by Django 3.2.25 on 2024-10-18 10:28

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

class Migration(migrations.Migration):

dependencies = [
('viewer', '0073_merge_20241018_0956'),
]

def temporary_name(apps, schema_editor):
CompoundIdentifier = apps.get_model('viewer', 'CompoundIdentifier')

for idf in CompoundIdentifier.objects.all():
idf.name_type = idf.type.name
idf.save()

def reverse_temporary_name(apps, schema_editor):
pass


# this contains some edits, the automatically constructed
# migration was not in the correct order, so I had to move things
# around to preserve data
operations = [
migrations.AddField(
model_name='compoundidentifier',
name='name_type',
field=models.TextField(null=True),
),
migrations.RunPython(temporary_name, reverse_temporary_name),
migrations.RemoveField(
model_name='compoundidentifier',
name='type',
),
migrations.RemoveField(
model_name='compoundidentifiertype',
name='id',
),
migrations.AlterField(
model_name='compoundidentifiertype',
name='name',
field=models.TextField(primary_key=True, serialize=False),
),
]
33 changes: 33 additions & 0 deletions viewer/migrations/0074_auto_20241028_1617.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.25 on 2024-10-28 16:17

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('viewer', '0073_merge_20241028_1554'),
]

operations = [
migrations.AddField(
model_name='compound',
name='modeled_smiles_canon',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='compound',
name='modeled_smiles_soakdb',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='compound',
name='soaked_smiles_canon',
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name='compound',
name='soaked_smiles_soakdb',
field=models.TextField(blank=True, null=True),
),
]
31 changes: 31 additions & 0 deletions viewer/migrations/0075_remove_compoundidentifier_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 3.2.25 on 2024-10-18 10:38

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


class Migration(migrations.Migration):

dependencies = [
('viewer', '0074_auto_20241018_1028'),
]

def relink_type(apps, schema_editor):
CompoundIdentifier = apps.get_model('viewer', 'CompoundIdentifier')
CompoundIdentifierType = apps.get_model('viewer', 'CompoundIdentifierType')

for idf in CompoundIdentifier.objects.all():
idf.type = CompoundIdentifierType.objects.get(name=idf.name_type)
idf.save()

def reverse_relink_type(apps, schema_editor):
pass

operations = [
migrations.AddField(
model_name='compoundidentifier',
name='type',
field=models.ForeignKey(null=True, to_field='name', on_delete=django.db.models.deletion.CASCADE, to='viewer.compoundidentifiertype'),
),
migrations.RunPython(relink_type, reverse_relink_type),
]
18 changes: 18 additions & 0 deletions viewer/migrations/0076_compoundidentifier_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.25 on 2024-10-18 10:39

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


class Migration(migrations.Migration):

dependencies = [
('viewer', '0075_remove_compoundidentifier_type'),
]

operations = [
migrations.RemoveField(
model_name='compoundidentifier',
name='name_type',
),
]
19 changes: 19 additions & 0 deletions viewer/migrations/0077_alter_compoundidentifier_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.25 on 2024-10-18 10:40

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


class Migration(migrations.Migration):

dependencies = [
('viewer', '0076_compoundidentifier_type'),
]

operations = [
migrations.AlterField(
model_name='compoundidentifier',
name='type',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='viewer.compoundidentifiertype'),
),
]
Loading