forked from enviPath/enviPy
Current Dev State
This commit is contained in:
0
epdb/__init__.py
Normal file
0
epdb/__init__.py
Normal file
36
epdb/admin.py
Normal file
36
epdb/admin.py
Normal file
@ -0,0 +1,36 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import User, Group, UserPackagePermission, GroupPackagePermission, Setting, SimpleAmbitRule
|
||||
|
||||
|
||||
class UserAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
class GroupAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
class UserPackagePermissionAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
class GroupPackagePermissionAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
class SettingAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
admin.site.register(User, UserAdmin)
|
||||
admin.site.register(Group, GroupAdmin)
|
||||
admin.site.register(UserPackagePermission, UserPackagePermissionAdmin)
|
||||
admin.site.register(GroupPackagePermission, GroupPackagePermissionAdmin)
|
||||
admin.site.register(Setting, SettingAdmin)
|
||||
|
||||
|
||||
class SimpleAmbitRuleAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
admin.site.register(SimpleAmbitRule, SimpleAmbitRuleAdmin)
|
||||
108
epdb/api.py
Normal file
108
epdb/api.py
Normal file
@ -0,0 +1,108 @@
|
||||
from typing import List
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from ninja import Router, Schema, Field
|
||||
from ninja.errors import HttpError
|
||||
from ninja.pagination import paginate
|
||||
from ninja.security import HttpBearer
|
||||
|
||||
from .logic import PackageManager
|
||||
from .models import User, Compound, APIToken
|
||||
|
||||
|
||||
class BearerTokenAuth(HttpBearer):
|
||||
def authenticate(self, request, token):
|
||||
for token_obj in APIToken.objects.select_related("user").all():
|
||||
if token_obj.check_token(token) and token_obj.is_valid():
|
||||
return token_obj.user
|
||||
raise HttpError(401, "Invalid or expired token")
|
||||
|
||||
|
||||
def _anonymous_or_real(request):
|
||||
if request.user.is_authenticated and not request.user.is_anonymous:
|
||||
return request.user
|
||||
return get_user_model().objects.get(username='anonymous')
|
||||
|
||||
|
||||
router = Router(auth=BearerTokenAuth())
|
||||
|
||||
|
||||
class UserSchema(Schema):
|
||||
email: str
|
||||
username: str
|
||||
id: str = Field(None, alias="url")
|
||||
|
||||
|
||||
class PackageIn(Schema):
|
||||
name: str
|
||||
description: str
|
||||
|
||||
|
||||
class PackageOut(Schema):
|
||||
id: str = Field(None, alias="url")
|
||||
name: str
|
||||
reviewed: bool
|
||||
compound_links: str = None
|
||||
|
||||
@staticmethod
|
||||
def resolve_compound_links(obj):
|
||||
return f"{obj.url}/compound"
|
||||
|
||||
|
||||
class Error(Schema):
|
||||
message: str
|
||||
|
||||
|
||||
class CompoundSchema(Schema):
|
||||
name: str = Field(None, alias="name")
|
||||
id: str = Field(None, alias="url")
|
||||
smiles: str = Field(None, alias="default_structure.smiles")
|
||||
reviewed: bool = Field(None, alias="package.reviewed")
|
||||
|
||||
|
||||
@router.get("/user", response={200: List[UserSchema], 403: Error})
|
||||
def get_users(request):
|
||||
return User.objects.all()
|
||||
|
||||
|
||||
@router.get("/package", response={200: List[PackageOut], 403: Error})
|
||||
def get_packages(request):
|
||||
return PackageManager.get_all_readable_packages(request.user, include_reviewed=True)
|
||||
|
||||
|
||||
@router.post("/package", response=PackageOut)
|
||||
def create_package(request, package: PackageIn):
|
||||
user = request.auth
|
||||
name = package.name.strip()
|
||||
description = package.description.strip()
|
||||
|
||||
p = PackageManager.create_package(user, name, description=description)
|
||||
return p
|
||||
|
||||
|
||||
@router.get("/package/{uuid:package_uuid}", response={200: PackageOut, 403: Error})
|
||||
def get_package(request, package_uuid):
|
||||
try:
|
||||
return PackageManager.get_package_by_id(request.auth, package_id=package_uuid)
|
||||
except ValueError:
|
||||
return 403, {'message': f'Getting Package with id {package_uuid} failed due to insufficient rights!'}
|
||||
|
||||
|
||||
@router.get("/compound", response={200: List[CompoundSchema], 403: Error})
|
||||
@paginate
|
||||
def get_compounds(request):
|
||||
qs = Compound.objects.none()
|
||||
for p in PackageManager.get_reviewed_packages():
|
||||
qs |= Compound.objects.filter(package=p)
|
||||
return qs
|
||||
|
||||
|
||||
@router.get("/package/{uuid:package_uuid}/compound", response={200: List[CompoundSchema], 403: Error})
|
||||
@paginate
|
||||
def get_package_compounds(request, package_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.auth, package_uuid)
|
||||
return Compound.objects.filter(package=p)
|
||||
except ValueError:
|
||||
return 403, {
|
||||
'message': f'Getting Compounds for Package with id {package_uuid} failed due to insufficient rights!'}
|
||||
6
epdb/apps.py
Normal file
6
epdb/apps.py
Normal file
@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class EPDBConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'epdb'
|
||||
5
epdb/forms.py
Normal file
5
epdb/forms.py
Normal file
@ -0,0 +1,5 @@
|
||||
from django import forms
|
||||
|
||||
|
||||
class EmailLoginForm(forms.Form):
|
||||
email = forms.EmailField()
|
||||
492
epdb/logic.py
Normal file
492
epdb/logic.py
Normal file
@ -0,0 +1,492 @@
|
||||
import re
|
||||
import logging
|
||||
from typing import Union, List, Optional, Set, Dict
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import transaction
|
||||
|
||||
from epdb.models import User, Package, UserPackagePermission, GroupPackagePermission, Permission, Group, Setting, \
|
||||
EPModel, UserSettingPermission, Rule, Pathway, Node, Edge
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class UserManager(object):
|
||||
@staticmethod
|
||||
def create_user(username, email, password):
|
||||
# avoid circular import :S
|
||||
from .tasks import send_registration_mail
|
||||
# TODO flip to False
|
||||
u = get_user_model().objects.create_user(username, email, password, is_active=True)
|
||||
|
||||
# Create package
|
||||
package_name = f"{u.username}{'’' if u.username[-1] in 'sxzß' else 's'} Package"
|
||||
package_description = f"This package was generated during registration."
|
||||
p = PackageManager.create_package(u, package_name, package_description)
|
||||
u.default_package = p
|
||||
u.save()
|
||||
|
||||
if not u.is_active:
|
||||
# send email for verification
|
||||
send_registration_mail.delay(u.pk)
|
||||
|
||||
return u
|
||||
|
||||
@staticmethod
|
||||
def get_user(user_url):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_users():
|
||||
return []
|
||||
|
||||
|
||||
class GroupManager(object):
|
||||
|
||||
@staticmethod
|
||||
def create_group(owner):
|
||||
g = Group()
|
||||
g.name = 'enviPath Users'
|
||||
g.description = 'All enviPath Users'
|
||||
g.owner = owner
|
||||
g.save()
|
||||
|
||||
return g
|
||||
|
||||
@staticmethod
|
||||
def get_group_by_url(user, group_url):
|
||||
return GroupManager.get_group_by_id(user, group_url.split('/')[-1])
|
||||
|
||||
@staticmethod
|
||||
def get_group_by_id(user, group_id):
|
||||
g = Group.objects.get(uuid=group_id)
|
||||
|
||||
if user in g.user_member.all():
|
||||
return g
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_groups(user):
|
||||
return Group.objects.filter(user_member=user)
|
||||
|
||||
|
||||
class PackageManager(object):
|
||||
package_pattern = re.compile(r".*/package/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
|
||||
|
||||
@staticmethod
|
||||
def get_reviewed_packages():
|
||||
return Package.objects.filter(reviewed=True)
|
||||
|
||||
@staticmethod
|
||||
def readable(user, package):
|
||||
# TODO Owner!
|
||||
if UserPackagePermission.objects.filter(package=package, user=user).exists() or \
|
||||
GroupPackagePermission.objects.filter(package=package, group__in=user.groups.all()) or \
|
||||
package.reviewed is True or \
|
||||
user.is_superuser:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def writable(user, package):
|
||||
# TODO Owner!
|
||||
if UserPackagePermission.objects.filter(package=package, user=user, permission=Permission.WRITE).exists() or \
|
||||
GroupPackagePermission.objects.filter(package=package, group__in=user.groups.all(),
|
||||
permission=Permission.WRITE) or \
|
||||
user.is_superuser:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_package_by_url(user, package_url):
|
||||
match = re.findall(PackageManager.package_pattern, package_url)
|
||||
|
||||
if match:
|
||||
package_id = match[0].split('/')[-1]
|
||||
return PackageManager.get_package_by_id(user, package_id)
|
||||
else:
|
||||
raise ValueError("Requested URL {} does not contain a valid package identifier!".format(package_url))
|
||||
|
||||
@staticmethod
|
||||
def get_package_by_id(user, package_id):
|
||||
try:
|
||||
p = Package.objects.get(uuid=package_id)
|
||||
if PackageManager.readable(user, p):
|
||||
return p
|
||||
else:
|
||||
raise ValueError(
|
||||
"Insufficient permissions to access Package with ID {}".format(package_id))
|
||||
except Package.DoesNotExist:
|
||||
raise ValueError("Package with ID {} does not exist!".format(package_id))
|
||||
|
||||
@staticmethod
|
||||
def get_all_readable_packages(user, include_reviewed=False):
|
||||
# UserPermission only exists if at least read is granted...
|
||||
if user.is_superuser:
|
||||
qs = Package.objects.all()
|
||||
else:
|
||||
up = UserPackagePermission.objects.filter(user=user).values('package').distinct()
|
||||
qs = Package.objects.filter(id__in=up)
|
||||
|
||||
if include_reviewed:
|
||||
qs |= Package.objects.filter(reviewed=True)
|
||||
else:
|
||||
# remove package if user is owner and package is reviewed e.g. admin
|
||||
qs = qs.filter(reviewed=False)
|
||||
|
||||
return qs.distinct()
|
||||
|
||||
@staticmethod
|
||||
def get_all_writeable_packages(user):
|
||||
# UserPermission only exists if at least read is granted...
|
||||
if user.is_superuser:
|
||||
qs = Package.objects.all()
|
||||
else:
|
||||
up = UserPackagePermission.objects.filter(user=user, permission=Permission.WRITE).values(
|
||||
'package').distinct()
|
||||
qs = Package.objects.filter(id__in=up)
|
||||
|
||||
qs = qs.filter(reviewed=False)
|
||||
|
||||
return qs.distinct()
|
||||
|
||||
@staticmethod
|
||||
def get_packages():
|
||||
return Package.objects.all()
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
def create_package(current_user, name: str, description: str = None):
|
||||
p = Package()
|
||||
p.name = name
|
||||
p.description = description
|
||||
p.save()
|
||||
|
||||
up = UserPackagePermission()
|
||||
up.user = current_user
|
||||
up.package = p
|
||||
up.permission = UserPackagePermission.ALL[0]
|
||||
up.save()
|
||||
|
||||
return p
|
||||
|
||||
|
||||
class SettingManager(object):
|
||||
setting_pattern = re.compile(r".*/setting/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
|
||||
|
||||
@staticmethod
|
||||
def get_setting_by_url(user, setting_url):
|
||||
match = re.findall(SettingManager.setting_pattern, setting_url)
|
||||
|
||||
if match:
|
||||
setting_id = match[0].split('/')[-1]
|
||||
return SettingManager.get_setting_by_id(user, setting_id)
|
||||
else:
|
||||
raise ValueError("Requested URL {} does not contain a valid setting identifier!".format(setting_url))
|
||||
|
||||
@staticmethod
|
||||
def get_setting_by_id(user, setting_id):
|
||||
s = Setting.objects.get(uuid=setting_id)
|
||||
|
||||
if s.global_default or s.public or s.owner == user or user.is_superuser:
|
||||
return s
|
||||
|
||||
raise ValueError(
|
||||
"Insufficient permissions to access Setting with ID {}".format(setting_id))
|
||||
|
||||
@staticmethod
|
||||
def get_all_settings(user):
|
||||
sp = UserSettingPermission.objects.filter(user=user).values('setting').distinct()
|
||||
return Setting.objects.filter(id__in=sp)
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
def create_setting(user: User, name: str = None, description: str = None, max_nodes: int = None,
|
||||
max_depth: int = None, rule_packages: List[Package] = None, model: EPModel = None,
|
||||
model_threshold: float = None):
|
||||
s = Setting()
|
||||
s.name = name
|
||||
s.description = description
|
||||
s.max_nodes = max_nodes
|
||||
s.max_depth = max_depth
|
||||
s.model = model
|
||||
s.model_threshold = model_threshold
|
||||
|
||||
s.save()
|
||||
|
||||
if rule_packages is not None:
|
||||
for r in rule_packages:
|
||||
s.rule_packages.add(r)
|
||||
s.save()
|
||||
|
||||
usp = UserSettingPermission()
|
||||
usp.user = user
|
||||
usp.setting = s
|
||||
usp.permission = Permission.ALL[0]
|
||||
usp.save()
|
||||
|
||||
return s
|
||||
|
||||
@staticmethod
|
||||
def get_default_setting(user: User):
|
||||
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
def set_default_setting(user: User, setting: Setting):
|
||||
pass
|
||||
|
||||
|
||||
class SNode(object):
|
||||
|
||||
def __init__(self, smiles: str, depth: int):
|
||||
self.smiles = smiles
|
||||
self.depth = depth
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.smiles)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return self.smiles == other.smiles
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return f"SNode('{self.smiles}', {self.depth})"
|
||||
|
||||
|
||||
class SEdge(object):
|
||||
|
||||
def __init__(self, educts: Union[SNode, List[SNode]], products: Union[SNode | List[SNode]],
|
||||
rule: Optional['Rule'] = None):
|
||||
|
||||
if not isinstance(educts, list):
|
||||
educts = [educts]
|
||||
|
||||
self.educts = educts
|
||||
self.products = products
|
||||
self.rule = rule
|
||||
|
||||
def __hash__(self):
|
||||
full_hash = 0
|
||||
|
||||
for n in sorted(self.educts, key=lambda x: x.smiles):
|
||||
full_hash += hash(n)
|
||||
|
||||
for n in sorted(self.products, key=lambda x: x.smiles):
|
||||
full_hash += hash(n)
|
||||
|
||||
if self.rule is not None:
|
||||
full_hash += hash(self.rule)
|
||||
|
||||
return full_hash
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, SEdge):
|
||||
return False
|
||||
|
||||
if self.rule is not None and other.rule is None or \
|
||||
self.rule is None and other.rule is not None or \
|
||||
self.rule != other.rule:
|
||||
return False
|
||||
|
||||
if not (len(self.educts) == len(other.educts)):
|
||||
return False
|
||||
|
||||
for n1, n2 in zip(sorted(self.educts, key=lambda x: x.smiles), sorted(other.educts, key=lambda x: x.smiles)):
|
||||
if n1.smiles != n2.smiles:
|
||||
return False
|
||||
|
||||
if not (len(self.products) == len(other.products)):
|
||||
return False
|
||||
|
||||
for n1, n2 in zip(sorted(self.products, key=lambda x: x.smiles),
|
||||
sorted(other.products, key=lambda x: x.smiles)):
|
||||
if n1.smiles != n2.smiles:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
return f"SEdge({self.educts}, {self.products}, {self.rule})"
|
||||
|
||||
|
||||
class SPathway(object):
|
||||
|
||||
def __init__(self, root_nodes: Optional[Union[str, SNode, List[str | SNode]]] = None,
|
||||
persist: Optional['Pathway'] = None, prediction_setting: Optional[Setting] = None
|
||||
):
|
||||
self.root_nodes = []
|
||||
|
||||
self.persist = persist
|
||||
self.snode_persist_lookup: Dict[SNode, Node] = dict()
|
||||
self.sedge_persist_lookup: Dict[SEdge, Edge] = dict()
|
||||
self.prediction_setting = prediction_setting
|
||||
|
||||
if persist:
|
||||
for n in persist.root_nodes:
|
||||
snode = SNode(n.default_node_label.smiles, n.depth)
|
||||
self.root_nodes.append(snode)
|
||||
self.snode_persist_lookup[snode] = n
|
||||
else:
|
||||
if not isinstance(root_nodes, list):
|
||||
root_nodes = [root_nodes]
|
||||
|
||||
for n in root_nodes:
|
||||
if isinstance(n, str):
|
||||
self.root_nodes.append(SNode(n, 0))
|
||||
elif isinstance(n, SNode):
|
||||
self.root_nodes.append(n)
|
||||
|
||||
self.queue = list()
|
||||
self.smiles_to_node: Dict[str, SNode] = dict(**{n.smiles: n for n in self.root_nodes})
|
||||
self.edges: Set['SEdge'] = set()
|
||||
self.done = False
|
||||
|
||||
def num_nodes(self):
|
||||
return len(self.smiles_to_node.keys())
|
||||
|
||||
def depth(self):
|
||||
return max([v.depth for v in self.smiles_to_node.values()])
|
||||
|
||||
def _get_nodes_for_depth(self, depth: int):
|
||||
if depth == 0:
|
||||
return self.root_nodes
|
||||
|
||||
res = []
|
||||
for n in self.smiles_to_node.values():
|
||||
if n.depth == depth:
|
||||
res.append(n)
|
||||
|
||||
return sorted(res, key=lambda x: x.smiles)
|
||||
|
||||
def _get_edges_for_depth(self, depth: int):
|
||||
res = []
|
||||
for e in self.edges:
|
||||
for n in e.educts:
|
||||
if n.depth == depth:
|
||||
res.append(e)
|
||||
|
||||
return sorted(res, key=lambda x: hash(x))
|
||||
|
||||
def predict_step(self, from_depth: int = 0):
|
||||
substrates = self._get_nodes_for_depth(from_depth)
|
||||
|
||||
new_tp = False
|
||||
if substrates:
|
||||
for sub in substrates:
|
||||
candidates = self.prediction_setting.expand(self, sub)
|
||||
for cand_set in candidates:
|
||||
if cand_set:
|
||||
new_tp = True
|
||||
for cand in cand_set:
|
||||
cand_nodes = []
|
||||
for c in cand:
|
||||
if c not in self.smiles_to_node:
|
||||
self.smiles_to_node[c] = SNode(c, sub.depth + 1)
|
||||
|
||||
node = self.smiles_to_node[c]
|
||||
cand_nodes.append(node)
|
||||
|
||||
edge = SEdge(sub, cand_nodes, cand_set.rule)
|
||||
self.edges.add(edge)
|
||||
else:
|
||||
self.done = True
|
||||
|
||||
if new_tp and self.persist:
|
||||
self._sync_to_pathway()
|
||||
|
||||
def _sync_to_pathway(self):
|
||||
logger.info("Updating Pathway with SPathway")
|
||||
|
||||
for snode in self.smiles_to_node.values():
|
||||
if snode not in self.snode_persist_lookup:
|
||||
n = Node.create(self.persist, snode.smiles, snode.depth)
|
||||
self.snode_persist_lookup[snode] = n
|
||||
|
||||
for sedge in self.edges:
|
||||
if sedge not in self.sedge_persist_lookup:
|
||||
educt_nodes = []
|
||||
for snode in sedge.educts:
|
||||
educt_nodes.append(self.snode_persist_lookup[snode])
|
||||
|
||||
product_nodes = []
|
||||
for snode in sedge.products:
|
||||
product_nodes.append(self.snode_persist_lookup[snode])
|
||||
|
||||
e = Edge.create(self.persist, educt_nodes, product_nodes, sedge.rule)
|
||||
self.sedge_persist_lookup[sedge] = e
|
||||
|
||||
logger.info("Update done!")
|
||||
pass
|
||||
|
||||
def to_json(self):
|
||||
nodes = []
|
||||
edges = []
|
||||
|
||||
idx_lookup = {}
|
||||
|
||||
for i, s in enumerate(self.smiles_to_node):
|
||||
n = self.smiles_to_node[s]
|
||||
idx_lookup[s] = i
|
||||
|
||||
nodes.append({'depth': n.depth, 'smiles': n.smiles, 'id': i})
|
||||
|
||||
for edge in self.edges:
|
||||
from_idx = idx_lookup[edge.educts[0].smiles]
|
||||
to_indices = [idx_lookup[p.smiles] for p in edge.products]
|
||||
|
||||
e = {
|
||||
'from': from_idx,
|
||||
'to': to_indices,
|
||||
}
|
||||
|
||||
# if edge.rule:
|
||||
# e['rule'] = {
|
||||
# 'name': edge.rule.name,
|
||||
# 'id': edge.rule.url,
|
||||
# }
|
||||
edges.append(e)
|
||||
|
||||
return {
|
||||
'nodes': nodes,
|
||||
'edges': edges,
|
||||
}
|
||||
|
||||
def graph_to_tree_string(self):
|
||||
graph_json = self.to_json()
|
||||
nodes = {node['id']: node for node in graph_json['nodes']}
|
||||
edges = graph_json['edges']
|
||||
|
||||
children_map = {}
|
||||
for edge in edges:
|
||||
src = edge['from']
|
||||
for tgt in edge['to']:
|
||||
children_map.setdefault(src, []).append(tgt)
|
||||
|
||||
visited = set()
|
||||
|
||||
def recurse(node_id, prefix=''):
|
||||
if node_id in visited:
|
||||
return prefix + nodes[node_id]['smiles'] + " [loop detected]\n"
|
||||
visited.add(node_id)
|
||||
|
||||
line = prefix + nodes[node_id]['smiles'] + f" [{node_id}]\n"
|
||||
kids = children_map.get(node_id, [])
|
||||
for i, kid in enumerate(kids):
|
||||
if i == len(kids) - 1:
|
||||
branch = '└── '
|
||||
child_prefix = prefix + ' '
|
||||
else:
|
||||
branch = '├── '
|
||||
child_prefix = prefix + '│ '
|
||||
line += recurse(kid, prefix=prefix + branch)
|
||||
return line
|
||||
|
||||
root_nodes = [n['id'] for n in graph_json['nodes'] if n['depth'] == 0]
|
||||
result = ''
|
||||
for root in root_nodes:
|
||||
visited.clear()
|
||||
result += recurse(root)
|
||||
return result
|
||||
0
epdb/management/__init__.py
Normal file
0
epdb/management/__init__.py
Normal file
0
epdb/management/commands/__init__.py
Normal file
0
epdb/management/commands/__init__.py
Normal file
402
epdb/management/commands/bootstrap.py
Normal file
402
epdb/management/commands/bootstrap.py
Normal file
@ -0,0 +1,402 @@
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from uuid import UUID
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings as s
|
||||
from epdb.models import *
|
||||
from epdb.logic import UserManager, GroupManager, PackageManager, SettingManager
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
def create_users(self):
|
||||
|
||||
if not User.objects.filter(email='anon@lorsba.ch').exists():
|
||||
anon = UserManager.create_user("anonymous", "anon@lorsba.ch", "SuperSafe")
|
||||
else:
|
||||
anon = User.objects.get(email='anon@lorsba.ch')
|
||||
|
||||
if not User.objects.filter(email='admin@lorsba.ch').exists():
|
||||
admin = UserManager.create_user("admin", "admin@lorsba.ch", "SuperSafe",)
|
||||
admin.is_staff = True
|
||||
admin.is_superuser = True
|
||||
admin.save()
|
||||
else:
|
||||
admin = User.objects.get(email='admin@lorsba.ch')
|
||||
|
||||
g = GroupManager.create_group(admin)
|
||||
g.user_member.add(anon)
|
||||
g.save()
|
||||
|
||||
anon.default_group = g
|
||||
anon.save()
|
||||
|
||||
admin.default_group = g
|
||||
admin.save()
|
||||
|
||||
if not User.objects.filter(email='jebus@lorsba.ch').exists():
|
||||
jebus = UserManager.create_user("jebus", "jebus@lorsba.ch", "SuperSafe",)
|
||||
jebus.is_staff = True
|
||||
jebus.is_superuser = True
|
||||
jebus.save()
|
||||
else:
|
||||
jebus = User.objects.get(email='jebus@lorsba.ch')
|
||||
|
||||
g.user_member.add(jebus)
|
||||
g.save()
|
||||
|
||||
jebus.default_group = g
|
||||
jebus.save()
|
||||
|
||||
return anon, admin, g, jebus
|
||||
|
||||
def import_package(self, data, owner):
|
||||
# Start import
|
||||
pack = Package()
|
||||
pack.uuid = UUID(data['id'].split('/')[-1])
|
||||
pack.name = '{} - {}'.format(data['name'], datetime.now().strftime('%Y-%m-%d %H:%M'))
|
||||
pack.reviewed = True if data['reviewStatus'] == 'reviewed' else False
|
||||
pack.description = data['description']
|
||||
pack.save()
|
||||
|
||||
up = UserPackagePermission()
|
||||
up.user = owner
|
||||
up.package = pack
|
||||
up.permission = up.ALL
|
||||
up.save()
|
||||
|
||||
# Stores old_id to new_id
|
||||
mapping = {}
|
||||
|
||||
# Store compounds and its structures
|
||||
for compound in data['compounds']:
|
||||
comp = Compound()
|
||||
comp.package = pack
|
||||
comp.uuid = UUID(compound['id'].split('/')[-1])
|
||||
comp.name = compound['name']
|
||||
comp.description = compound['description']
|
||||
comp.aliases = compound['aliases']
|
||||
comp.save()
|
||||
|
||||
mapping[compound['id']] = comp.uuid
|
||||
|
||||
default_structure = None
|
||||
|
||||
for structure in compound['structures']:
|
||||
struc = CompoundStructure()
|
||||
# struc.object_url = Command.get_id(structure, keep_ids)
|
||||
struc.compound = comp
|
||||
struc.uuid = UUID(structure['id'].split('/')[-1])
|
||||
struc.name = structure['name']
|
||||
struc.description = structure['description']
|
||||
struc.smiles = structure['smiles']
|
||||
struc.save()
|
||||
mapping[structure['id']] = struc.uuid
|
||||
|
||||
if structure['id'] == compound['defaultStructure']['id']:
|
||||
default_structure = struc
|
||||
|
||||
struc.save()
|
||||
|
||||
if default_structure is None:
|
||||
raise ValueError('No default structure set')
|
||||
|
||||
comp.default_structure = default_structure
|
||||
comp.save()
|
||||
|
||||
print('Compounds imported...')
|
||||
|
||||
# Store simple and parallel-rules
|
||||
par_rules = []
|
||||
seq_rules = []
|
||||
|
||||
for rule in data['rules']:
|
||||
if rule['identifier'] == 'parallel-rule':
|
||||
par_rules.append(rule)
|
||||
continue
|
||||
if rule['identifier'] == 'sequential-rule':
|
||||
seq_rules.append(rule)
|
||||
continue
|
||||
r = SimpleAmbitRule()
|
||||
r.uuid = UUID(rule['id'].split('/')[-1])
|
||||
r.package = pack
|
||||
r.name = rule['name']
|
||||
r.description = rule['description']
|
||||
r.smirks = rule['smirks']
|
||||
r.reactant_filter_smarts = rule.get('reactantFilterSmarts', None)
|
||||
r.product_filter_smarts = rule.get('productFilterSmarts', None)
|
||||
r.save()
|
||||
|
||||
mapping[rule['id']] = r.uuid
|
||||
|
||||
print("Par: ", len(par_rules))
|
||||
print("Seq: ", len(seq_rules))
|
||||
|
||||
for par_rule in par_rules:
|
||||
r = ParallelRule()
|
||||
r.package = pack
|
||||
r.uuid = UUID(par_rule['id'].split('/')[-1])
|
||||
r.name = par_rule['name']
|
||||
r.description = par_rule['description']
|
||||
r.save()
|
||||
|
||||
mapping[par_rule['id']] = r.uuid
|
||||
|
||||
for simple_rule in par_rule['simpleRules']:
|
||||
if simple_rule['id'] in mapping:
|
||||
r.simple_rules.add(SimpleRule.objects.get(uuid=mapping[simple_rule['id']]))
|
||||
|
||||
r.save()
|
||||
|
||||
for seq_rule in seq_rules:
|
||||
r = SequentialRule()
|
||||
r.package = pack
|
||||
r.uuid = UUID(seq_rule['id'].split('/')[-1])
|
||||
r.name = seq_rule['name']
|
||||
r.description = seq_rule['description']
|
||||
r.save()
|
||||
|
||||
mapping[seq_rule['id']] = r.uuid
|
||||
|
||||
# m1 = Membership(
|
||||
# ... person=ringo,
|
||||
# ... group=beatles,
|
||||
# ... date_joined=date(1962, 8, 16),
|
||||
# ... invite_reason="Needed a new drummer.",
|
||||
# ... )
|
||||
# >>> m1.save()
|
||||
|
||||
for i, simple_rule in enumerate(seq_rule['simpleRules']):
|
||||
sro = SequentialRuleOrdering()
|
||||
sro.simple_rule = simple_rule
|
||||
sro.sequential_rule = r
|
||||
sro.order_index = i
|
||||
sro.save()
|
||||
# r.simple_rules.add(SimpleRule.objects.get(uuid=mapping[simple_rule['id']]))
|
||||
|
||||
r.save()
|
||||
|
||||
print('Rules imported...')
|
||||
|
||||
for reaction in data['reactions']:
|
||||
r = Reaction()
|
||||
r.package = pack
|
||||
r.uuid = UUID(reaction['id'].split('/')[-1])
|
||||
r.name = reaction['name']
|
||||
r.description = reaction['description']
|
||||
r.medlinereferences = reaction['medlinereferences'],
|
||||
r.multi_step = True if reaction['multistep'] == 'true' else False
|
||||
r.save()
|
||||
|
||||
mapping[reaction['id']] = r.uuid
|
||||
|
||||
for educt in reaction['educts']:
|
||||
r.educts.add(CompoundStructure.objects.get(uuid=mapping[educt['id']]))
|
||||
|
||||
for product in reaction['products']:
|
||||
r.products.add(CompoundStructure.objects.get(uuid=mapping[product['id']]))
|
||||
|
||||
if 'rules' in reaction:
|
||||
for rule in reaction['rules']:
|
||||
try:
|
||||
r.rules.add(Rule.objects.get(uuid=mapping[rule['id']]))
|
||||
except Exception as e:
|
||||
print(f"Rule with id {rule['id']} not found!")
|
||||
print(e)
|
||||
|
||||
r.save()
|
||||
|
||||
print('Reactions imported...')
|
||||
|
||||
for pathway in data['pathways']:
|
||||
pw = Pathway()
|
||||
pw.package = pack
|
||||
pw.uuid = UUID(pathway['id'].split('/')[-1])
|
||||
pw.name = pathway['name']
|
||||
pw.description = pathway['description']
|
||||
pw.save()
|
||||
|
||||
mapping[pathway['id']] = pw.uuid
|
||||
|
||||
out_nodes_mapping = defaultdict(set)
|
||||
|
||||
root_node = None
|
||||
|
||||
for node in pathway['nodes']:
|
||||
n = Node()
|
||||
n.uuid = UUID(node['id'].split('/')[-1])
|
||||
n.name = node['name']
|
||||
n.pathway = pw
|
||||
n.depth = node['depth']
|
||||
n.default_node_label = CompoundStructure.objects.get(uuid=mapping[node['defaultNodeLabel']['id']])
|
||||
n.save()
|
||||
|
||||
mapping[node['id']] = n.uuid
|
||||
|
||||
for node_label in node['nodeLabels']:
|
||||
n.node_labels.add(CompoundStructure.objects.get(uuid=mapping[node_label['id']]))
|
||||
|
||||
n.save()
|
||||
|
||||
for out_edge in node['outEdges']:
|
||||
out_nodes_mapping[n.uuid].add(out_edge)
|
||||
|
||||
for edge in pathway['edges']:
|
||||
e = Edge()
|
||||
e.uuid = UUID(edge['id'].split('/')[-1])
|
||||
e.name = edge['name']
|
||||
e.pathway = pw
|
||||
e.description = edge['description']
|
||||
e.edge_label = Reaction.objects.get(uuid=mapping[edge['edgeLabel']['id']])
|
||||
e.save()
|
||||
|
||||
mapping[edge['id']] = e.uuid
|
||||
|
||||
for start_node in edge['startNodes']:
|
||||
e.start_nodes.add(Node.objects.get(uuid=mapping[start_node]))
|
||||
|
||||
for end_node in edge['endNodes']:
|
||||
e.end_nodes.add(Node.objects.get(uuid=mapping[end_node]))
|
||||
|
||||
e.save()
|
||||
|
||||
for k, v in out_nodes_mapping.items():
|
||||
n = Node.objects.get(uuid=k)
|
||||
for v1 in v:
|
||||
n.out_edges.add(Edge.objects.get(uuid=mapping[v1]))
|
||||
n.save()
|
||||
|
||||
print('Pathways imported...')
|
||||
|
||||
print('Import statistics:')
|
||||
print('Package {} stored'.format(pack.url))
|
||||
print('Imported {} compounds'.format(Compound.objects.filter(package=pack).count()))
|
||||
print('Imported {} rules'.format(Rule.objects.filter(package=pack).count()))
|
||||
print('Imported {} reactions'.format(Reaction.objects.filter(package=pack).count()))
|
||||
print('Imported {} pathways'.format(Pathway.objects.filter(package=pack).count()))
|
||||
|
||||
print("Fixing Node depths...")
|
||||
total_pws = Pathway.objects.filter(package=pack).count()
|
||||
for p, pw in enumerate(Pathway.objects.filter(package=pack)):
|
||||
print(pw.url)
|
||||
in_count = defaultdict(lambda: 0)
|
||||
out_count = defaultdict(lambda: 0)
|
||||
|
||||
for e in pw.edges:
|
||||
# TODO check if this will remain
|
||||
for react in e.start_nodes.all():
|
||||
out_count[str(react.uuid)] += 1
|
||||
|
||||
for prod in e.end_nodes.all():
|
||||
in_count[str(prod.uuid)] += 1
|
||||
|
||||
root_nodes = []
|
||||
for n in pw.nodes:
|
||||
num_parents = in_count[str(n.uuid)]
|
||||
if num_parents == 0:
|
||||
# must be a root node or unconnected node
|
||||
if n.depth != 0:
|
||||
n.depth = 0
|
||||
n.save()
|
||||
|
||||
# Only root node may have children
|
||||
if out_count[str(n.uuid)] > 0:
|
||||
root_nodes.append(n)
|
||||
|
||||
levels = [root_nodes]
|
||||
seen = set()
|
||||
# Do a bfs to determine depths starting with level 0 a.k.a. root nodes
|
||||
for i, level_nodes in enumerate(levels):
|
||||
new_level = []
|
||||
for n in level_nodes:
|
||||
for e in n.out_edges.all():
|
||||
for prod in e.end_nodes.all():
|
||||
if str(prod.uuid) not in seen:
|
||||
old_depth = prod.depth
|
||||
if old_depth != i + 1:
|
||||
print(f'updating depth from {old_depth} to {i + 1}')
|
||||
prod.depth = i + 1
|
||||
prod.save()
|
||||
|
||||
new_level.append(prod)
|
||||
|
||||
seen.add(str(n.uuid))
|
||||
|
||||
if new_level:
|
||||
levels.append(new_level)
|
||||
|
||||
print(f'{p + 1}/{total_pws} fixed.')
|
||||
|
||||
return pack
|
||||
|
||||
def create_default_setting(self, owner, packages):
|
||||
s = SettingManager.create_setting(
|
||||
owner,
|
||||
name='Global Default Setting',
|
||||
description='Global Default Setting containing BBD Rules and Max 30 Nodes and Max Depth of 8',
|
||||
max_nodes=30,
|
||||
max_depth=5,
|
||||
rule_packages=packages,
|
||||
model=None,
|
||||
model_threshold=None
|
||||
)
|
||||
|
||||
return s
|
||||
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def handle(self, *args, **options):
|
||||
# Create users
|
||||
anon, admin, g, jebus = self.create_users()
|
||||
|
||||
# Import Packages
|
||||
packages = [
|
||||
'EAWAG-BBD.json',
|
||||
'EAWAG-SOIL.json',
|
||||
'EAWAG-SLUDGE.json',
|
||||
]
|
||||
|
||||
mapping = {}
|
||||
for p in packages:
|
||||
print(f"Importing {p}...")
|
||||
package_data = json.loads(open(s.BASE_DIR / 'fixtures' / p).read())
|
||||
imported_package = self.import_package(package_data, admin)
|
||||
mapping[p.replace('.json', '')] = imported_package
|
||||
|
||||
setting = self.create_default_setting(admin, [mapping['EAWAG-BBD']])
|
||||
setting.public = True
|
||||
setting.save()
|
||||
setting.make_global_default()
|
||||
|
||||
for u in [anon, jebus]:
|
||||
usp = UserSettingPermission()
|
||||
usp.user = u
|
||||
usp.setting = setting
|
||||
usp.permission = Permission.READ[0]
|
||||
usp.save()
|
||||
|
||||
# Create Model Package
|
||||
pack = PackageManager.create_package(admin, "Public Prediction Models", "Package to make Prediction Models publicly available")
|
||||
pack.reviewed = True
|
||||
pack.save()
|
||||
|
||||
# Create RR
|
||||
ml_model = MLRelativeReasoning.create(
|
||||
pack,
|
||||
'ECC - BBD - T0.5',
|
||||
'ML Relative Reasoning',
|
||||
[mapping['EAWAG-BBD']],
|
||||
[mapping['EAWAG-BBD']],
|
||||
[],
|
||||
0.5
|
||||
)
|
||||
|
||||
X, y = ml_model.build_dataset()
|
||||
ml_model.build_model(X, y)
|
||||
ml_model.evaluate_model()
|
||||
|
||||
# If available create EnviFormerModel
|
||||
if s.ENVIFORMER_PRESENT:
|
||||
enviFormer_model = EnviFormer.create(pack, 'EnviFormer - T0.5', 'EnviFormer Model with Threshold 0.5', 0.5)
|
||||
571
epdb/migrations/0001_initial.py
Normal file
571
epdb/migrations/0001_initial.py
Normal file
@ -0,0 +1,571 @@
|
||||
# Generated by Django 5.2.1 on 2025-06-16 13:57
|
||||
|
||||
import datetime
|
||||
import django.contrib.auth.models
|
||||
import django.contrib.auth.validators
|
||||
import django.contrib.postgres.fields
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Compound',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EPModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Permission',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('permission', models.CharField(choices=[('read', 'Read'), ('write', 'Write'), ('all', 'All')], max_length=32)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Package',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('reviewed', models.BooleanField(default=False, verbose_name='Reviewstatus')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Rule',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
|
||||
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('email', models.EmailField(max_length=254, unique=True)),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user',
|
||||
'verbose_name_plural': 'users',
|
||||
'abstract': False,
|
||||
},
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='APIToken',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('hashed_key', models.CharField(max_length=128, unique=True)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('expires_at', models.DateTimeField(blank=True, default=datetime.datetime(2025, 9, 14, 13, 57, 57, 138459, tzinfo=datetime.timezone.utc), null=True)),
|
||||
('name', models.CharField(blank=True, help_text='Optional name for the token', max_length=100)),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CompoundStructure',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
('smiles', models.TextField(verbose_name='SMILES')),
|
||||
('normalized_structure', models.BooleanField(default=False)),
|
||||
('compound', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.compound')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='compound',
|
||||
name='default_structure',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='compound_default_structure', to='epdb.compoundstructure', verbose_name='Default Structure'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Edge',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EnviFormer',
|
||||
fields=[
|
||||
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||
('threshold', models.FloatField(default=0.5)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.epmodel',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PluginModel',
|
||||
fields=[
|
||||
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.epmodel',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='RuleBaseRelativeReasoning',
|
||||
fields=[
|
||||
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.epmodel',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Group',
|
||||
fields=[
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(verbose_name='Group name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('group_member', models.ManyToManyField(related_name='groups_in_group', to='epdb.group', verbose_name='Group member')),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Group Owner')),
|
||||
('user_member', models.ManyToManyField(related_name='users_in_group', to=settings.AUTH_USER_MODEL, verbose_name='User members')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='default_group',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_group', to='epdb.group', verbose_name='Default Group'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(to='epdb.group', verbose_name='groups'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Node',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
('depth', models.IntegerField(verbose_name='Node depth')),
|
||||
('default_node_label', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='default_node_structure', to='epdb.compoundstructure', verbose_name='Default Node Label')),
|
||||
('node_labels', models.ManyToManyField(related_name='node_structures', to='epdb.compoundstructure', verbose_name='All Node Labels')),
|
||||
('out_edges', models.ManyToManyField(to='epdb.edge', verbose_name='Outgoing Edges')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edge',
|
||||
name='end_nodes',
|
||||
field=models.ManyToManyField(related_name='edge_products', to='epdb.node', verbose_name='End Nodes'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edge',
|
||||
name='start_nodes',
|
||||
field=models.ManyToManyField(related_name='edge_educts', to='epdb.node', verbose_name='Start Nodes'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='epmodel',
|
||||
name='package',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='compound',
|
||||
name='package',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='default_package',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.package', verbose_name='Default Package'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SequentialRule',
|
||||
fields=[
|
||||
('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.rule')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.rule',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SimpleRule',
|
||||
fields=[
|
||||
('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.rule')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.rule',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Pathway',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='node',
|
||||
name='pathway',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.pathway', verbose_name='belongs to'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edge',
|
||||
name='pathway',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.pathway', verbose_name='belongs to'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Reaction',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||
('multi_step', models.BooleanField(verbose_name='Multistep Reaction')),
|
||||
('medline_references', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), null=True, size=None, verbose_name='Medline References')),
|
||||
('educts', models.ManyToManyField(related_name='reaction_educts', to='epdb.compoundstructure', verbose_name='Educts')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||
('products', models.ManyToManyField(related_name='reaction_products', to='epdb.compoundstructure', verbose_name='Products')),
|
||||
('rules', models.ManyToManyField(related_name='reaction_rule', to='epdb.rule', verbose_name='Rule')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edge',
|
||||
name='edge_label',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.reaction', verbose_name='Edge label'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Scenario',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('date', models.DateField(null=True, verbose_name='Study date')),
|
||||
('type', models.CharField(default='Not specified', max_length=256)),
|
||||
('additional_information', models.JSONField(verbose_name='Additional Information')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rule',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='reaction',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='pathway',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='node',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='edge',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='compoundstructure',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='compound',
|
||||
name='scenarios',
|
||||
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Setting',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('public', models.BooleanField(default=False)),
|
||||
('global_default', models.BooleanField(default=False)),
|
||||
('max_depth', models.IntegerField(default=5, verbose_name='Setting Max Depth')),
|
||||
('max_nodes', models.IntegerField(default=30, verbose_name='Setting Max Number of Nodes')),
|
||||
('model_threshold', models.FloatField(blank=True, default=0.25, null=True, verbose_name='Setting Model Threshold')),
|
||||
('model', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.epmodel', verbose_name='Setting EPModel')),
|
||||
('rule_packages', models.ManyToManyField(related_name='setting_rule_packages', to='epdb.package', verbose_name='Setting Rule Packages')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='default_setting',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.setting', verbose_name='The users default settings'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MLRelativeReasoning',
|
||||
fields=[
|
||||
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||
('threshold', models.FloatField(default=0.5)),
|
||||
('model_status', models.CharField(choices=[('INITIAL', 'Initial'), ('INITIALIZING', 'Model is initializing.'), ('BUILDING', 'Model is building.'), ('BUILT_NOT_EVALUATED', 'Model is built and can be used for predictions, Model is not evaluated yet.'), ('EVALUATING', 'Model is evaluating'), ('FINISHED', 'Model has finished building and evaluation.'), ('ERROR', 'Model has failed.')], default='INITIAL')),
|
||||
('eval_results', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('data_packages', models.ManyToManyField(related_name='data_packages', to='epdb.package', verbose_name='Data Packages')),
|
||||
('eval_packages', models.ManyToManyField(related_name='eval_packages', to='epdb.package', verbose_name='Evaluation Packages')),
|
||||
('rule_packages', models.ManyToManyField(related_name='rule_packages', to='epdb.package', verbose_name='Rule Packages')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.epmodel',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ApplicabilityDomain',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||
('num_neighbours', models.FloatField(default=5)),
|
||||
('reliability_threshold', models.FloatField(default=0.5)),
|
||||
('local_compatibilty_threshold', models.FloatField(default=0.5)),
|
||||
('model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.mlrelativereasoning')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SimpleAmbitRule',
|
||||
fields=[
|
||||
('simplerule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.simplerule')),
|
||||
('smirks', models.TextField(verbose_name='SMIRKS')),
|
||||
('reactant_filter_smarts', models.TextField(null=True, verbose_name='Reactant Filter SMARTS')),
|
||||
('product_filter_smarts', models.TextField(null=True, verbose_name='Product Filter SMARTS')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.simplerule',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SimpleRDKitRule',
|
||||
fields=[
|
||||
('simplerule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.simplerule')),
|
||||
('reaction_smarts', models.TextField(verbose_name='SMIRKS')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.simplerule',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SequentialRuleOrdering',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('order_index', models.IntegerField()),
|
||||
('sequential_rule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.sequentialrule')),
|
||||
('simple_rule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.simplerule')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sequentialrule',
|
||||
name='simple_rules',
|
||||
field=models.ManyToManyField(through='epdb.SequentialRuleOrdering', to='epdb.simplerule', verbose_name='Simple rules'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ParallelRule',
|
||||
fields=[
|
||||
('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.rule')),
|
||||
('simple_rules', models.ManyToManyField(to='epdb.simplerule', verbose_name='Simple rules')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
'base_manager_name': 'objects',
|
||||
},
|
||||
bases=('epdb.rule',),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='compound',
|
||||
unique_together={('uuid', 'package')},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='GroupPackagePermission',
|
||||
fields=[
|
||||
('permission_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='epdb.permission')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.group', verbose_name='Permission to')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Permission on')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('package', 'group')},
|
||||
},
|
||||
bases=('epdb.permission',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserPackagePermission',
|
||||
fields=[
|
||||
('permission_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='epdb.permission')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Permission on')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Permission to')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('package', 'user')},
|
||||
},
|
||||
bases=('epdb.permission',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserSettingPermission',
|
||||
fields=[
|
||||
('permission_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='epdb.permission')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||
('setting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.setting', verbose_name='Permission on')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Permission to')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('setting', 'user')},
|
||||
},
|
||||
bases=('epdb.permission',),
|
||||
),
|
||||
]
|
||||
0
epdb/migrations/__init__.py
Normal file
0
epdb/migrations/__init__.py
Normal file
1487
epdb/models.py
Normal file
1487
epdb/models.py
Normal file
File diff suppressed because it is too large
Load Diff
50
epdb/tasks.py
Normal file
50
epdb/tasks.py
Normal file
@ -0,0 +1,50 @@
|
||||
import logging
|
||||
from celery.signals import worker_process_init
|
||||
from celery import shared_task
|
||||
from epdb.models import Pathway, Node, Edge, EPModel, Setting
|
||||
from epdb.logic import SPathway
|
||||
|
||||
from utilities.chem import FormatConverter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@shared_task(queue='background')
|
||||
def mul(a, b):
|
||||
return a * b
|
||||
|
||||
|
||||
@shared_task(queue='predict')
|
||||
def predict_simple(model_pk: int, smiles: str):
|
||||
mod = EPModel.objects.get(id=model_pk)
|
||||
res = mod.predict(smiles)
|
||||
return res
|
||||
|
||||
|
||||
@shared_task(queue='background')
|
||||
def send_registration_mail(user_pk: int):
|
||||
pass
|
||||
|
||||
|
||||
@shared_task(queue='model')
|
||||
def build_model(model_pk: int):
|
||||
mod = EPModel.objects.get(id=model_pk)
|
||||
X, y = mod.build_dataset()
|
||||
mod.build_model(X, y)
|
||||
|
||||
|
||||
@shared_task(queue='model')
|
||||
def evaluate_model(model_pk: int):
|
||||
mod = EPModel.objects.get(id=model_pk)
|
||||
mod.evaluate_model()
|
||||
|
||||
|
||||
@shared_task(queue='predict')
|
||||
def predict(pw_pk: int, pred_setting_pk: int):
|
||||
pw = Pathway.objects.get(id=pw_pk)
|
||||
setting = Setting.objects.get(id=pred_setting_pk)
|
||||
spw = SPathway(prediction_setting=setting, persist=pw)
|
||||
level = 0
|
||||
while not spw.done:
|
||||
spw.predict_step(from_depth=level)
|
||||
level += 1
|
||||
3
epdb/tests.py
Normal file
3
epdb/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
77
epdb/urls.py
Normal file
77
epdb/urls.py
Normal file
@ -0,0 +1,77 @@
|
||||
from django.urls import path, re_path
|
||||
|
||||
from . import views as v
|
||||
# from sesame.views import LoginView
|
||||
|
||||
UUID = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'
|
||||
|
||||
urlpatterns = [
|
||||
# Sesame
|
||||
# path("login/", v.EmailLoginView.as_view(), name="email_login"),
|
||||
# path("login/auth/", LoginView.as_view(), name="login"),
|
||||
|
||||
# Home
|
||||
re_path(r'^$', v.index, name='index'),
|
||||
|
||||
# Top level urls
|
||||
re_path(r'^package$', v.packages, name='packages'),
|
||||
re_path(r'^compound$', v.compounds, name='compounds'),
|
||||
re_path(r'^rule$', v.rules, name='rules'),
|
||||
re_path(r'^reaction$', v.reactions, name='reactions'),
|
||||
re_path(r'^pathway$', v.pathways, name='pathways'),
|
||||
re_path(r'^scenario$', v.scenarios, name='scenarios'),
|
||||
re_path(r'^model$', v.models, name='model'),
|
||||
re_path(r'^user$', v.users, name='users'),
|
||||
re_path(r'^group$', v.groups, name='groups'),
|
||||
re_path(r'^search$', v.search, name='search'),
|
||||
|
||||
|
||||
# User Detail
|
||||
re_path(rf'^user/(?P<user_uuid>{UUID})', v.user, name='user'),
|
||||
# Group Detail
|
||||
re_path(rf'^group/(?P<group_uuid>{UUID})$', v.group, name='group_detail'),
|
||||
|
||||
# "in package" urls
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})$', v.package, name='package_detail'),
|
||||
# Compound
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/compound$', v.package_compounds, name='package compound list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/compound/(?P<compound_uuid>{UUID})$', v.package_compound, name='package compound detail'),
|
||||
# Compound Structure
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/compound/(?P<compound_uuid>{UUID})/structure$', v.package_compound_structures, name='package compound structure list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/compound/(?P<compound_uuid>{UUID})/structure/(?P<structure_uuid>{UUID})$', v.package_compound_structure, name='package compound structure detail'),
|
||||
# Rule
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/rule$', v.package_rules, name='package rule list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/rule/(?P<rule_uuid>{UUID})$', v.package_rule, name='package rule detail'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/simple-ambit-rule/(?P<rule_uuid>{UUID})$', v.package_rule, name='package rule detail'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/simple-rdkit-rule/(?P<rule_uuid>{UUID})$', v.package_rule, name='package rule detail'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/parallel-rule/(?P<rule_uuid>{UUID})$', v.package_rule, name='package rule detail'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/sequential-rule/(?P<rule_uuid>{UUID})$', v.package_rule, name='package rule detail'),
|
||||
# Reaction
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/reaction$', v.package_reactions, name='package reaction list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/reaction/(?P<reaction_uuid>{UUID})$', v.package_reaction, name='package reaction detail'),
|
||||
# # Pathway
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/pathway$', v.package_pathways, name='package pathway list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})$', v.package_pathway, name='package pathway detail'),
|
||||
# Pathway Nodes
|
||||
# re_path(rf'^package/(?P<package_uuid>{UUID})/pathway(?P<pathway_uuid>{UUID})/node$', v.package_pathway_nodes, name='package pathway node list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/node/(?P<node_uuid>{UUID})$', v.package_pathway_node, name='package pathway node detail'),
|
||||
# Pathway Edges
|
||||
# re_path(rf'^package/(?P<package_uuid>{UUID})/pathway(?P<pathway_uuid>{UUID})/edge$', v.package_pathway_edges, name='package pathway edge list'),
|
||||
# re_path(rf'^package/(?P<package_uuid>{UUID})/pathway(?P<pathway_uuid>{UUID})/edge/(?P<edge_uuid>{UUID})$', v.package_pathway_edge, name='package pathway edge detail'),
|
||||
# Scenario
|
||||
# re_path(rf'^package/(?P<package_uuid>{UUID})/scenario', v.package_scenarios, name='package scenario list'),
|
||||
# re_path(rf'^package/(?P<package_uuid>{UUID})/scenario/(?P<scenario_uuid>{UUID})$', v.package_scenarios, name='package scenario detail'),
|
||||
# Model
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/model$', v.package_models, name='package model list'),
|
||||
re_path(rf'^package/(?P<package_uuid>{UUID})/model/(?P<model_uuid>{UUID})$', v.package_model,name='package model detail'),
|
||||
|
||||
re_path(r'^setting$', v.settings, name='settings'),
|
||||
re_path(rf'^setting/(?P<setting_uuid>{UUID})', v.setting, name='setting'),
|
||||
|
||||
re_path(r'^indigo/info$', v.indigo, name='indigo_info'),
|
||||
re_path(r'^indigo/aromatize$', v.aromatize, name='indigo_aromatize'),
|
||||
re_path(r'^indigo/dearomatize$', v.dearomatize, name='indigo_dearomatize'),
|
||||
re_path(r'^indigo/layout$', v.layout, name='indigo_layout'),
|
||||
|
||||
re_path(r'^depict$', v.depict, name='depict')
|
||||
]
|
||||
1356
epdb/views.py
Normal file
1356
epdb/views.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user