class MoleculePic(models.Model): format = models.ForeignKey(PictureFormat, on_delete=models.CASCADE) molecule = models.ForeignKey(Molecule, on_delete=models.CASCADE, related_name='pics') image = models.ImageField(upload_to='compounds/pics/', storage=OverwriteStorage())
class ChEMBLBioassayData(models.Model): compound = models.ForeignKey(Compound, null=False) target_data = models.ForeignKey(ChEMBLTargetData, null=False) assay_id = models.CharField(max_length=32, blank=True) ingredient_cmpd_id = models.CharField(max_length=32, blank=True) units = models.CharField(max_length=32, blank=True) bioactivity_type = models.CharField(max_length=32, blank=True) value = models.FloatField(null=True) operator = models.CharField(max_length=32, blank=True) activity_comment = models.CharField(max_length=64, blank=True) target_confidence = models.IntegerField(null=True) class Meta: verbose_name = 'ChEMBL Bioassay Data' verbose_name_plural = verbose_name def compound_link(self): return '<a href="%s">%s</a>' % (reverse("admin:compound_db_compound_change", args=(self.compound.pk,)) , escape(self.compound)) compound_link.allow_tags = True compound_link.short_description = 'Compound' def target_data_link(self): return '<a href="%s">%s</a>' % (reverse("admin:compound_db_chembltargetdata_change", args=(self.target_data.pk,)) , escape(self.target_data)) target_data_link.allow_tags = True target_data_link.short_description = 'Target Data'
class MolSetFile(PolymorphicModel): molset = models.ForeignKey(MolSet, on_delete=models.CASCADE, null=False, related_name='files') file = models.FileField(null=False, upload_to='compounds/sets/files/', storage=OverwriteStorage()) export = models.ForeignKey(MolSetExport, null=True, on_delete=models.CASCADE, related_name='files') @staticmethod def create(molset, filename, file): file.name = filename return MolSetFile.objects.create(molset=molset, file=file)
class Activity(PolymorphicModel): value = models.FloatField(blank=False) type = models.ForeignKey(ActivityTypes, on_delete=models.CASCADE, null=False) units = models.ForeignKey(ActivityUnits, on_delete=models.CASCADE, null=True) source = models.ForeignKey(ActivitySet, on_delete=NON_POLYMORPHIC_CASCADE, blank=False, related_name='activities') molecule = models.ForeignKey(Molecule, on_delete=models.CASCADE, blank=False, related_name='activities') parent = models.ForeignKey("self", null=True, on_delete=models.CASCADE, related_name="children") def __str__(self): return '%s object (%s=%f)' % (self.__class__.__name__, self.type.value, self.value)
class PurchaseCompound(models.Model): """ Join table for purchase and its compounds. """ compound = models.ForeignKey(Molecule) purchase = models.ForeignKey(Purchase) amount = models.FloatField() def __str__(self): return "PurchaseCompound ({}): compound {} in purchase {} ".format( self.id, self.compound.id, self.purchase.id)
class OrderCompound(models.Model): """ Join table for order and its compounds. """ compound = models.ForeignKey(Molecule) order = models.ForeignKey(Order) amount = models.FloatField() def __str__(self): return "OrderCompound ({}): compound {} in order {} ".format( self.id, self.compound.id, self.order.id)
class Place(models.Model): """ Represents one place which consists of room and building. """ building = models.ForeignKey(Building) room = models.ForeignKey(Room) class Meta: unique_together = ("building", "room") def __str__(self): return "Place ({}): {}/{}".format(self.id, self.building.name, self.room.code)
class Molecule(PolymorphicModel): entity = models.ForeignKey(ChemicalEntity, on_delete=models.CASCADE, null=False, related_name='molecules') providers = models.ManyToManyField(MolSet, blank=False, related_name='molecules') @classmethod def create(cls, canonicalSMILES, inchiKey, rdMol, *args, **kwargs): ret = cls.objects.create( entity=ChemicalEntity.objects.get_or_create( canonicalSMILES=canonicalSMILES, inchiKey=inchiKey, rdMol=rdMol )[0], *args, **kwargs ) return ret def __str__(self): return '%s object <%s>' % (self.__class__.__name__, self.smiles) @property def canonicalSMILES(self): return self.entity.canonicalSMILES @property def inchi(self): return self.entity.inchi @property def inchiKey(self): return self.entity.inchiKey @property def rdMol(self): return self.entity.rdMol @property def fingerprint(self): return self.entity.fingerprint @property def smiles(self): """ A shorthand to get a nice human readable SMILES string directly from representation. """ return Chem.MolToSmiles(self.rdMol, isomericSmiles=True, canonical=True) def getPic(self, format): format = PictureFormat.objects.get_or_create(extension=f'.{format}')[0] qs = self.pics.filter(format=format) pic = qs.all()[0] if qs.exists() else helpers.createPic(self, format) return pic @property def mainPic(self): return self.getPic('svg')
class Purchase(models.Model): """ Represents one purchase. """ compounds = models.ManyToManyField(Molecule, through="PurchaseCompound") person = models.ForeignKey(Person) status = models.ForeignKey(PurchaseStatus) purchase_internal_id = models.CharField(max_length=32, unique=True) created = models.DateTimeField(auto_now_add=True) def __str__(self): return "Purchase ({} / {}): for {} | compounds: {} | {}".format( self.id, self.purchase_internal_id, str(self.person), self.compounds.count(), str(self.status)) def save(self, update=True, *args, **kwargs): if not update: today_date = datetime.date.today() today_min = datetime.datetime.combine(datetime.date.today(), datetime.time.min) today_max = datetime.datetime.combine(datetime.date.today(), datetime.time.max) try: today_last_purchase = Purchase.objects.filter( created__range=(today_min, today_max)).latest("id") print(today_last_purchase.id) self.purchase_internal_id = "{:%Y-%m-%d}/{}".format( datetime.date.today(), today_last_purchase.id + 1) except ObjectDoesNotExist: self.purchase_internal_id = "{:%Y-%m-%d}/1".format(today_date) super(Purchase, self).save(*args, **kwargs) class Meta: ordering = ['id']
class Person(models.Model): """ Represents one person. """ user = models.OneToOneField(User, on_delete=models.CASCADE) name = models.CharField(max_length=64) surname = models.CharField(max_length=128) place = models.ForeignKey(Place) telephone = models.CharField(max_length=16) def __str__(self): return "Person ({}): {}, {} @ {}".format(self.id, self.surname, self.name, str(self.place)) class Meta: ordering = ['id']
class ActivitySet(TaskShortcutsMixIn, TaskMixin, DataSet): objects = PolymorphicTaskManager() class ActivityTypeSummary: def __init__(self, activityType: "ActivityTypes", compounds: "Molecule", occurences: "Activity"): self.type = activityType self.moleculesTotal = compounds self.activitiesTotal = occurences class ActivitySetSummary: def generateTypeSummaries(self): typeInfo = self.getTypeInfo() ret = [] for info in typeInfo: actype = ActivityTypes.objects.get(pk=info['type']) ret.append( ActivitySet.ActivityTypeSummary(actype, info['molecules'], info['occurences'])) return ret def getTypeInfo(self): return self.activities.values('type').annotate( occurences=Count('id'), molecules=Count('molecule', distinct=True)).order_by('-molecules') def __init__(self, activitySet: "ActivitySet"): self._activitySet = activitySet self.activities = Activity.objects.filter(source=self._activitySet) self.molecules = Molecule.objects.filter( activities__source=self._activitySet).distinct() self.typeSummaries = self.generateTypeSummaries() self.activitiesTotal = self.activities.count() self.moleculesTotal = self.molecules.count() molecules = models.ForeignKey(MolSet, blank=False, null=False, on_delete=models.CASCADE, related_name="activities") def cleanForModelling(self, activity_type: "ActivityTypes") -> tuple: """ A procedure that returns molecules as Molecule instances and their activities to be used by QSAR and other models. This is a very basic implementation and should be overridden in children. :return: Tuple of list objects (same length) -> Molecule instances and their associated activity values for models """ activities = [] mols = [] units = None for activity in Activity.objects.filter(source=self, type=activity_type): units = activity.units # TODO: we should check if all units are the same mols.append(activity.molecule) activities.append(activity.value) return mols, activities, units def getSummary(self): return self.ActivitySetSummary(self) def getActivityTypes(self): return set([x.type.value for x in self.activities.all()])
class MolSetExport(models.Model): name = models.CharField(max_length=128, blank=False, null=False) description = models.TextField(max_length=10000, blank=True) molset = models.ForeignKey(MolSet, on_delete=models.CASCADE, null=False, related_name='exports') exporter = models.ForeignKey(MolSetExporter, on_delete=models.CASCADE, null=False)
class CompoundTrivialNames(models.Model): name = models.CharField(max_length=128, blank=False, unique=True) compound = models.ForeignKey(Compound)