Skip to content

Commit

Permalink
Merge pull request #461 from matthiaskoenig/develop
Browse files Browse the repository at this point in the history
Changes for v0.7.0
  • Loading branch information
matthiaskoenig authored Nov 4, 2019
2 parents 2cb54b9 + d3bcfd6 commit 6f774de
Show file tree
Hide file tree
Showing 14 changed files with 191 additions and 108 deletions.
2 changes: 1 addition & 1 deletion backend/pkdb_app/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
Definition of version string.
"""
__version__ = "0.6.9"
__version__ = "0.7.0"
38 changes: 30 additions & 8 deletions backend/pkdb_app/categorials/behaviours.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
from pkdb_app.categorials.models import ureg, MeasurementType
from pkdb_app.substances.models import Substance
from pkdb_app.behaviours import Sidable
from pkdb_app.categorials.managers import AnnotatableManager
from django.db import models
from pkdb_app.utils import CHAR_MAX_LENGTH_LONG, CHAR_MAX_LENGTH
import pint

ureg = pint.UnitRegistry()
# Units
ureg.define('cups = count')
ureg.define('beverages = count')
ureg.define('none = count')
ureg.define('yr = year')
ureg.define('percent = 0.01*count')
ureg.define('U = 60*10**6*mol/second')
ureg.define('IU = [activity_amount]')
ureg.define('NO_UNIT = [no_unit]')


def map_field(fields):
Expand Down Expand Up @@ -51,13 +63,23 @@ class Meta:
abstract = True


class Annotatable(Sidable):
description = models.TextField(blank=True, null=True)
name = models.CharField(max_length=CHAR_MAX_LENGTH)
annotations = models.ManyToManyField('categorials.Annotation')

objects = AnnotatableManager()

class Meta:
abstract = True


class ExMeasurementTypeable(ValueableNotBlank, ValueableMapNotBlank):
measurement_type = models.CharField(max_length=CHAR_MAX_LENGTH, null=True)
measurement_type_map = models.CharField(max_length=CHAR_MAX_LENGTH_LONG, null=True)

choice = models.CharField(max_length=CHAR_MAX_LENGTH_LONG, null=True)
choice_map = models.CharField(max_length=CHAR_MAX_LENGTH_LONG, null=True)
# substance = models.ForeignKey(Substance, null=True, on_delete=models.PROTECT)
substance = models.CharField(max_length=CHAR_MAX_LENGTH, null=True)
substance_map = models.CharField(max_length=CHAR_MAX_LENGTH_LONG, null=True)

Expand All @@ -66,8 +88,8 @@ class Meta:


class MeasurementTypeable(ValueableNotBlank):
measurement_type = models.ForeignKey(MeasurementType, on_delete=models.CASCADE)
substance = models.ForeignKey(Substance, null=True, on_delete=models.PROTECT)
measurement_type = models.ForeignKey('categorials.MeasurementType', on_delete=models.CASCADE)
substance = models.ForeignKey('substances.Substance', null=True, on_delete=models.PROTECT)
choice = models.CharField(max_length=CHAR_MAX_LENGTH_LONG, null=True)

class Meta:
Expand Down Expand Up @@ -124,7 +146,7 @@ def is_removeable_substance_dimension(self):
if substance and substance.mass:
dimension_of_substance = self.measurement_type.p_unit(self.unit).dimensionality.get('[substance]')
if dimension_of_substance != 0:
return (True, dimension_of_substance)
return True, dimension_of_substance

return (False, None)

Expand All @@ -139,9 +161,9 @@ def remove_substance_dimension(self):
molar_weight = ureg("g/mol") * self.substance.mass
p_unit = self.measurement_type.p_unit(self.unit)
this_quantity = p_unit * molar_weight ** dimension
return (this_quantity.magnitude, str(this_quantity.units))
return this_quantity.magnitude, str(this_quantity.units)
else:
return (1, self.unit)
return 1, self.unit

def normalize(self):
""" Normalizes the units.
Expand Down
7 changes: 7 additions & 0 deletions backend/pkdb_app/categorials/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ class MeasurementTypeDocument(Document):
"label": string_field("label")
}
)
synonyms = ObjectField(
attr="synonyms",
multi=True,
properties={
"name": string_field("name"),
}
)
creator = string_field("creator_username")
description = string_field('description')

Expand Down
10 changes: 5 additions & 5 deletions backend/pkdb_app/categorials/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from pkdb_app.utils import update_or_create_multiple


class ChoiceManager(models.Manager):
class AnnotatableManager(models.Manager):
def create(self, *args, **kwargs):
annotations = kwargs.pop('annotations', [])
choice = super().create(*args, **kwargs)
update_or_create_multiple(choice, annotations, 'annotations', lookup_fields=["term", "relation"])
choice.save()
return choice
instance = super().create(*args, **kwargs)
update_or_create_multiple(instance, annotations, 'annotations', lookup_fields=["term", "relation"])
instance.save()
return instance
78 changes: 42 additions & 36 deletions backend/pkdb_app/categorials/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,17 @@
FIXME: Some duplication to pkdb_data/categorials
"""
import pint
from pint import UndefinedUnitError
import numpy as np

from numbers import Number

from django.db import models
from pkdb_app.categorials.managers import ChoiceManager
from pkdb_app.users.models import User
from pkdb_app.utils import CHAR_MAX_LENGTH, create_choices, _validate_requried_key, CHAR_MAX_LENGTH_LONG

ureg = pint.UnitRegistry()
from pkdb_app.categorials.managers import AnnotatableManager
from pkdb_app.users.models import User
from pkdb_app.utils import CHAR_MAX_LENGTH, create_choices, _validate_requried_key
from pkdb_app.categorials.behaviours import Annotatable, ureg

# Units
ureg.define('cups = count')
ureg.define('beverages = count')
ureg.define('none = count')
ureg.define('yr = year')
ureg.define('percent = 0.01*count')
ureg.define('U = 60*10**6*mol/second')
ureg.define('IU = [activity_amount]')
ureg.define('NO_UNIT = [no_unit]')

NO_UNIT = 'NO_UNIT'

NUMERIC_TYPE = "numeric"
CATEGORIAL_TYPE = "categorial"
BOOLEAN_TYPE = "boolean"
Expand Down Expand Up @@ -57,7 +43,11 @@ def p_unit(self):
return ureg(self.name).u





class Annotation(models.Model):
""" Annotation Model """
term = models.CharField(max_length=CHAR_MAX_LENGTH)
relation = models.CharField(max_length=CHAR_MAX_LENGTH, )
collection = models.CharField(max_length=CHAR_MAX_LENGTH, null=True)
Expand All @@ -67,49 +57,52 @@ class Annotation(models.Model):

class Choice(models.Model):
"""Choice Model"""
description = models.TextField(blank=True, null=True)
name = models.CharField(max_length=CHAR_MAX_LENGTH)
annotations = models.ManyToManyField(Annotation)
description = models.TextField(blank=True, null=True)
objects = ChoiceManager()
objects = AnnotatableManager()


class Tissue(models.Model):
name = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
class Tissue(Annotatable):
""" Tissue Model """

creator = models.ForeignKey(User, related_name="tissues", on_delete=models.CASCADE)
url_slug = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
description = models.TextField(blank=True, null=True)


class Route(models.Model):
name = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
class Route(Annotatable):
""" Route Model """

creator = models.ForeignKey(User, related_name="routes", on_delete=models.CASCADE)
url_slug = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
description = models.TextField(blank=True, null=True)


class Application(models.Model):
name = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
class Application(Annotatable):
""" Application Model """
creator = models.ForeignKey(User, related_name="applications", on_delete=models.CASCADE)
url_slug = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
description = models.TextField(blank=True, null=True)


class Form(models.Model):
name = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
class Form(Annotatable):
""" Form Model """

creator = models.ForeignKey(User, related_name="forms", on_delete=models.CASCADE)
url_slug = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
description = models.TextField(blank=True, null=True)


class MeasurementType(models.Model):
name = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
""" MeasurementType Model """
#fixme: add sid to pkdb_data and use Annotatable
url_slug = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
units = models.ManyToManyField(Unit, related_name="measurement_types")
dtype = models.CharField(max_length=CHAR_MAX_LENGTH, choices=DTYPE_CHOICES)
creator = models.ForeignKey(User, related_name="measurement_types", on_delete=models.CASCADE)
choices = models.ManyToManyField(Choice, related_name="measurement_types")

description = models.TextField(blank=True, null=True)
name = models.CharField(max_length=CHAR_MAX_LENGTH)
annotations = models.ManyToManyField(Annotation)
objects = AnnotatableManager()

def __str__(self):
return self.name
Expand Down Expand Up @@ -143,7 +136,8 @@ def valid_dimensions_str(self):
def dimension_to_n_unit(self):
return {str(n_unit_p.dimensionality): n_unit_p for n_unit_p in self.n_p_units}

def p_unit(self, unit):
@staticmethod
def p_unit(unit):
try:
return ureg(unit)
except (UndefinedUnitError, AttributeError):
Expand Down Expand Up @@ -171,7 +165,8 @@ def is_valid_unit(self, unit):

def validate_unit(self, unit):
if not self.is_valid_unit(unit):
msg = f"For measurement type `{self.name}` the unit [{unit}] with dimension {self.unit_dimension(unit)} is not allowed."
msg = f"For measurement type `{self.name}` the unit [{unit}] with dimension {self.unit_dimension(unit)} " \
f"is not allowed."
raise ValueError(
{"unit": msg, "Only units with the following dimensions are allowed:": self.valid_dimensions_str,
"Units are allowed which can be converted to the following normalized units:": self.n_units})
Expand Down Expand Up @@ -239,7 +234,8 @@ def validate_choice(self, choice):
f"For encoding substances use the `substance` field."
raise ValueError({"choice": msg})
elif self.choices.exists():
msg = f"{choice}. A choice is required for `{self.name}`. Allowed choices are: `{list(self.choices_list())}`."
msg = f"{choice}. A choice is required for `{self.name}`." \
f" Allowed choices are: `{list(self.choices_list())}`."
raise ValueError({"choice": msg})

@property
Expand Down Expand Up @@ -297,3 +293,13 @@ def creator_username(self):
:return: list of normalized units in the data format of pint
"""
return self.creator.username

class Synonym(models.Model):
"""Units Model"""
name = models.CharField(max_length=CHAR_MAX_LENGTH, unique=True)
substance = models.ForeignKey('substances.Substance', on_delete=models.CASCADE, related_name="synonyms", null=True)
tissue = models.ForeignKey(Tissue, on_delete=models.CASCADE, related_name="synonyms", null=True)
route = models.ForeignKey(Route, on_delete=models.CASCADE, related_name="synonyms", null=True)
form = models.ForeignKey(Form, on_delete=models.CASCADE, related_name="synonyms", null=True)
application = models.ForeignKey(Application, on_delete=models.CASCADE, related_name="synonyms", null=True)
measurement_type = models.ForeignKey(MeasurementType, on_delete=models.CASCADE, related_name="synonyms", null=True)
Loading

0 comments on commit 6f774de

Please sign in to comment.