diff --git a/build/build.py b/build/build.py index 8ee11a4..d5080eb 100755 --- a/build/build.py +++ b/build/build.py @@ -97,7 +97,7 @@ def main(): print(f"{len(codes_to_check)} of these need to be checked") # Check - for code in tqdm(codes_to_check): + for code in tqdm(codes_to_check[:500]): with transaction.atomic(): process_pdb_code(code) diff --git a/build/factories.py b/build/factories.py index f38cb2c..39de6dd 100644 --- a/build/factories.py +++ b/build/factories.py @@ -78,7 +78,20 @@ def create_site_record(site_dict, pdb_record, index, chains_dict): atoms_dict = {} for res in sorted(site_dict["residues"], key=lambda r: r.id): chain_record = chains_dict[res.chain.id] if isinstance(res, atomium.Residue) else None - create_residue_record(res, chain_record, site_record, atoms_dict) + create_residue_record(res, site_record, atoms_dict, chain_record) + + # Add secondary residues + second_residues, stabiliser_contacts = set(), set() + for residue in site_dict["residues"]: + for atom in residue.atoms(): + nearby = atom.nearby_atoms(3) + for nearby_atom in nearby: + if isinstance(nearby_atom.het, atomium.Residue)\ + and nearby_atom.het not in site_dict["residues"]: + second_residues.add(nearby_atom.het) + stabiliser_contacts.add((atom, nearby_atom)) + for res in second_residues: + create_residue_record(res, site_record, atoms_dict, primary=False) # Create bond records for metal, atoms in sorted(site_dict["metals"].items(), key=lambda a: a[0].id): @@ -86,7 +99,10 @@ def create_site_record(site_dict, pdb_record, index, chains_dict): CoordinateBond.objects.create( metal=metals_dict[metal.id], atom=atoms_dict[atom] ) - + for primary, secondary in stabiliser_contacts: + StabilisingBond.objects.create( + primary_atom=atoms_dict[primary], secondary_atom=atoms_dict[secondary] + ) return site_record @@ -98,7 +114,7 @@ def create_chain_interaction_record(chain_record, site_record, sequence): ) -def create_residue_record(residue, chain_record, site_record, atoms_dict): +def create_residue_record(residue, site_record, atoms_dict, chain_record=None, primary=True): """Creates a Residue record along with its atoms, from information given. A dictionary of atoms must be given to make coordinate bonds later.""" @@ -115,7 +131,7 @@ def create_residue_record(residue, chain_record, site_record, atoms_dict): signature = ".".join(signature) residue_record = Residue.objects.create( residue_number=numeric_id, chain_identifier=residue.chain.id, - insertion_code=insertion, chain_signature=signature, + insertion_code=insertion, chain_signature=signature, primary=primary, name=residue.name, chain=chain_record, site=site_record, atomium_id=residue.id ) for atom in sorted(residue.atoms(), key=lambda a: a.id): diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index dc7159f..84215c3 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2 on 2019-06-16 17:53 +# Generated by Django 2.2 on 2019-09-25 13:27 from django.db import migrations, models import django.db.models.deletion @@ -94,6 +94,17 @@ class Migration(migrations.Migration): 'db_table': 'zinc_sites', }, ), + migrations.CreateModel( + name='StabilisingBond', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('primary_atom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='primary_atoms', to='core.Atom')), + ('secondary_atom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='secondary_atoms', to='core.Atom')), + ], + options={ + 'db_table': 'stabilising_bonds', + }, + ), migrations.CreateModel( name='Residue', fields=[ @@ -104,6 +115,7 @@ class Migration(migrations.Migration): ('atomium_id', models.CharField(max_length=128)), ('chain_identifier', models.CharField(max_length=128)), ('chain_signature', models.CharField(blank=True, max_length=128)), + ('primary', models.BooleanField(default=True)), ('chain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.Chain')), ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.ZincSite')), ], @@ -142,7 +154,7 @@ class Migration(migrations.Migration): ('metal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Metal')), ], options={ - 'db_table': 'bonds', + 'db_table': 'coordinate_bonds', }, ), migrations.CreateModel( diff --git a/core/migrations/0002_residue_primary.py b/core/migrations/0002_residue_primary.py deleted file mode 100644 index 19f1734..0000000 --- a/core/migrations/0002_residue_primary.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2 on 2019-09-19 16:08 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='residue', - name='primary', - field=models.BooleanField(default=True), - ), - ] diff --git a/core/models.py b/core/models.py index 8d4ad29..42bc8d0 100644 --- a/core/models.py +++ b/core/models.py @@ -170,7 +170,18 @@ class CoordinateBond(models.Model): """A bond between a metal atom and a liganding atom.""" class Meta: - db_table = "bonds" + db_table = "coordinate_bonds" metal = models.ForeignKey(Metal, on_delete=models.CASCADE) - atom = models.ForeignKey(Atom, on_delete=models.CASCADE) \ No newline at end of file + atom = models.ForeignKey(Atom, on_delete=models.CASCADE) + + + +class StabilisingBond(models.Model): + """A bond between a primary residie atom and a secondary residue atom.""" + + class Meta: + db_table = "stabilising_bonds" + + primary_atom = models.ForeignKey(Atom, on_delete=models.CASCADE, related_name="primary_atoms") + secondary_atom = models.ForeignKey(Atom, on_delete=models.CASCADE, related_name="secondary_atoms") \ No newline at end of file diff --git a/tests/test_build.py b/tests/test_build.py index 69ce6c7..f6a0845 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -192,7 +192,7 @@ def test_can_work_properly(self): self.assertEqual(metal.z, 15.281) self.assertEqual(metal.omission_reason, None) - residues = site.residue_set.all() + residues = site.residue_set.filter(primary=True) self.assertEqual(residues.count(), 4) res1 = residues.get(atomium_id="A.94") self.assertEqual(res1.name, "HIS")