forked from enviPath/enviPy
[Feature] More on Legacy API (#142)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#142
This commit is contained in:
@ -2,11 +2,24 @@ from typing import List, Dict, Optional, Any
|
|||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import redirect
|
||||||
from ninja import Router, Schema, Field, Form
|
from ninja import Router, Schema, Field, Form
|
||||||
|
|
||||||
from utilities.chem import FormatConverter
|
from utilities.chem import FormatConverter
|
||||||
from .logic import PackageManager
|
from .logic import PackageManager, UserManager, SettingManager
|
||||||
from .models import Compound, CompoundStructure, Package, User, UserPackagePermission, Rule, Reaction, Scenario, Pathway
|
from .models import (
|
||||||
|
Compound,
|
||||||
|
CompoundStructure,
|
||||||
|
Package,
|
||||||
|
User,
|
||||||
|
UserPackagePermission,
|
||||||
|
Rule,
|
||||||
|
Reaction,
|
||||||
|
Scenario,
|
||||||
|
Pathway,
|
||||||
|
Node,
|
||||||
|
Edge, SimpleAmbitRule
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _anonymous_or_real(request):
|
def _anonymous_or_real(request):
|
||||||
@ -22,16 +35,9 @@ router = Router()
|
|||||||
class Error(Schema):
|
class Error(Schema):
|
||||||
message: str
|
message: str
|
||||||
|
|
||||||
|
#################
|
||||||
class SimpleObject(Schema):
|
# SimpleObjects #
|
||||||
id: str = Field(None, alias="url")
|
#################
|
||||||
name: str = Field(None, alias="name")
|
|
||||||
reviewStatus: bool = Field(None, alias="package.reviewed")
|
|
||||||
|
|
||||||
|
|
||||||
################
|
|
||||||
# Login/Logout #
|
|
||||||
################
|
|
||||||
class SimpleUser(Schema):
|
class SimpleUser(Schema):
|
||||||
id: str = Field(None, alias="url")
|
id: str = Field(None, alias="url")
|
||||||
identifier: str = 'user'
|
identifier: str = 'user'
|
||||||
@ -39,8 +45,82 @@ class SimpleUser(Schema):
|
|||||||
email: str = Field(None, alias='email')
|
email: str = Field(None, alias='email')
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleGroup(Schema):
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
identifier: str = 'group'
|
||||||
|
name: str = Field(None, alias='name')
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleSetting(Schema):
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
identifier: str = 'setting'
|
||||||
|
name: str = Field(None, alias='name')
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleObject(Schema):
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
reviewStatus: str = Field(None, alias="review_status")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_review_status(obj):
|
||||||
|
if isinstance(obj, Package):
|
||||||
|
return 'reviewed' if obj.reviewed else 'unreviewed'
|
||||||
|
elif hasattr(obj, 'package'):
|
||||||
|
return 'reviewed' if obj.package.reviewed else 'unreviewed'
|
||||||
|
elif isinstance(obj, CompoundStructure):
|
||||||
|
return 'reviewed' if obj.compound.package.reviewed else 'unreviewed'
|
||||||
|
elif isinstance(obj, Node) or isinstance(obj, Edge):
|
||||||
|
return 'reviewed' if obj.pathway.package.reviewed else 'unreviewed'
|
||||||
|
else:
|
||||||
|
raise ValueError('Object has no package')
|
||||||
|
|
||||||
|
|
||||||
|
class SimplePackage(SimpleObject):
|
||||||
|
identifier: str = 'package'
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleCompound(SimpleObject):
|
||||||
|
identifier: str = 'compound'
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleCompoundStructure(SimpleObject):
|
||||||
|
identifier: str = 'structure'
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleRule(SimpleObject):
|
||||||
|
identifier: str = 'rule'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_url(obj: Rule):
|
||||||
|
return obj.url.replace('-ambit-', '-').replace('-rdkit-', '-')
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleReaction(SimpleObject):
|
||||||
|
identifier: str = 'reaction'
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleScenario(SimpleObject):
|
||||||
|
identifier: str = 'scenario'
|
||||||
|
|
||||||
|
|
||||||
|
class SimplePathway(SimpleObject):
|
||||||
|
identifier: str = 'pathway'
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleNode(SimpleObject):
|
||||||
|
identifier: str = 'node'
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleEdge(SimpleObject):
|
||||||
|
identifier: str = 'edge'
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
# Login/Logout #
|
||||||
|
################
|
||||||
@router.post("/", response={200: SimpleUser, 403: Error})
|
@router.post("/", response={200: SimpleUser, 403: Error})
|
||||||
def login(request, loginusername: Form[str], loginpassword: Form[str], hiddenMethod: Form[str]):
|
def login(request, loginusername: Form[str], loginpassword: Form[str]):
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth import login
|
from django.contrib.auth import login
|
||||||
email = User.objects.get(username=loginusername).email
|
email = User.objects.get(username=loginusername).email
|
||||||
@ -49,21 +129,68 @@ def login(request, loginusername: Form[str], loginpassword: Form[str], hiddenMet
|
|||||||
login(request, user)
|
login(request, user)
|
||||||
return user
|
return user
|
||||||
else:
|
else:
|
||||||
return 403, {'message': 'Invalid username or password'}
|
return 403, {'message': 'Invalid username and/or password'}
|
||||||
|
|
||||||
|
|
||||||
class SimpleGroup(Schema):
|
########
|
||||||
id: str
|
# User #
|
||||||
identifier: str = 'group'
|
########
|
||||||
name: str
|
class UserWrapper(Schema):
|
||||||
|
user: List[SimpleUser]
|
||||||
|
|
||||||
|
|
||||||
|
class UserSchema(Schema):
|
||||||
|
affiliation: Dict[str, str] = Field(None, alias="affiliation")
|
||||||
|
defaultGroup: 'SimpleGroup' = Field(None, alias="default_group")
|
||||||
|
defaultPackage: 'SimplePackage' = Field(None, alias="default_package")
|
||||||
|
defaultSetting: 'SimpleSetting' = Field(None, alias="default_setting")
|
||||||
|
email: str = Field(None, alias="email")
|
||||||
|
forename: str = 'not specified'
|
||||||
|
groups: List['SimpleGroup'] = Field([], alias="groups")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
identifier: str = 'user'
|
||||||
|
link: str = 'empty'
|
||||||
|
name: str = Field(None, alias="username")
|
||||||
|
surname: str = 'not specified'
|
||||||
|
settings: List['SimpleSetting'] = Field([], alias="settings")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_affiliation(obj: User):
|
||||||
|
# TODO
|
||||||
|
return {
|
||||||
|
"city": "not specified",
|
||||||
|
"country": "not specified",
|
||||||
|
"workplace": "not specified"
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_settings(obj: User):
|
||||||
|
return SettingManager.get_all_settings(obj)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/user", response={200: UserWrapper, 403: Error})
|
||||||
|
def get_users(request, whoami: str = None):
|
||||||
|
if whoami:
|
||||||
|
return {'user': [request.user]}
|
||||||
|
else:
|
||||||
|
return {'user': User.objects.all()}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/user/{uuid:user_uuid}", response={200: UserSchema, 403: Error})
|
||||||
|
def get_user(request, user_uuid):
|
||||||
|
try:
|
||||||
|
u = UserManager.get_user_by_id(request.user, user_uuid)
|
||||||
|
return u
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
'message': f'Getting User with id {user_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# Package #
|
# Package #
|
||||||
###########
|
###########
|
||||||
class SimplePackage(SimpleObject):
|
class PackageWrapper(Schema):
|
||||||
identifier: str = 'package'
|
package: List['PackageSchema']
|
||||||
reviewStatus: bool = Field(None, alias="reviewed")
|
|
||||||
|
|
||||||
|
|
||||||
class PackageSchema(Schema):
|
class PackageSchema(Schema):
|
||||||
@ -138,10 +265,6 @@ class PackageSchema(Schema):
|
|||||||
return 'reviewed' if obj.reviewed else 'unreviewed'
|
return 'reviewed' if obj.reviewed else 'unreviewed'
|
||||||
|
|
||||||
|
|
||||||
class PackageWrapper(Schema):
|
|
||||||
package: List['PackageSchema']
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/package", response={200: PackageWrapper, 403: Error})
|
@router.get("/package", response={200: PackageWrapper, 403: Error})
|
||||||
def get_packages(request):
|
def get_packages(request):
|
||||||
return {'package': PackageManager.get_all_readable_packages(request.user, include_reviewed=True)}
|
return {'package': PackageManager.get_all_readable_packages(request.user, include_reviewed=True)}
|
||||||
@ -156,11 +279,58 @@ def get_package(request, package_uuid):
|
|||||||
'message': f'Getting Package with id {package_uuid} failed due to insufficient rights!'}
|
'message': f'Getting Package with id {package_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/package")
|
||||||
|
def create_packages(request, packageName: Form[str], packageDescription: Optional[str] = Form(None)):
|
||||||
|
try:
|
||||||
|
if packageName.strip() == '':
|
||||||
|
raise ValueError('Package name cannot be empty!')
|
||||||
|
|
||||||
|
new_pacakge = PackageManager.create_package(request.user, packageName, packageDescription)
|
||||||
|
return redirect(new_pacakge.url)
|
||||||
|
except ValueError as e:
|
||||||
|
return 400, {'message': str(e)}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/package/{uuid:package_uuid}", response={200: PackageSchema | Any , 400: Error})
|
||||||
|
def update_package(
|
||||||
|
request,
|
||||||
|
package_uuid,
|
||||||
|
packageDescription: Optional[str] = Form(None),
|
||||||
|
hiddenMethod: Optional[str] = Form(None),
|
||||||
|
exportAsJson: Optional[str] = Form(None),
|
||||||
|
permissions: Optional[str] = Form(None),
|
||||||
|
ppsURI: Optional[str] = Form(None),
|
||||||
|
read: Optional[str] = Form(None),
|
||||||
|
write: Optional[str] = Form(None),
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
|
|
||||||
|
if hiddenMethod:
|
||||||
|
if hiddenMethod == 'DELETE':
|
||||||
|
p.delete()
|
||||||
|
|
||||||
|
elif packageDescription and packageDescription.strip() != '':
|
||||||
|
p.description = packageDescription
|
||||||
|
p.save()
|
||||||
|
return
|
||||||
|
elif exportAsJson == 'true':
|
||||||
|
pack_json = PackageManager.export_package(p, include_models=False, include_external_identifiers=False)
|
||||||
|
return pack_json
|
||||||
|
elif all([permissions, ppsURI, read]):
|
||||||
|
PackageManager.update_permissions
|
||||||
|
elif all([permissions, ppsURI, write]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
except ValueError as e:
|
||||||
|
return 400, {'message': str(e)}
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Compound / CompoundStructure #
|
# Compound / CompoundStructure #
|
||||||
################################
|
################################
|
||||||
class SimpleCompound(SimpleObject):
|
class CompoundWrapper(Schema):
|
||||||
identifier: str = 'compound'
|
compound: List['SimpleCompound']
|
||||||
|
|
||||||
|
|
||||||
class CompoundPathwayScenario(Schema):
|
class CompoundPathwayScenario(Schema):
|
||||||
@ -218,15 +388,6 @@ class CompoundSchema(Schema):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class CompoundWrapper(Schema):
|
|
||||||
compound: List['SimpleCompound']
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleCompoundStructure(SimpleObject):
|
|
||||||
identifier: str = 'structure'
|
|
||||||
reviewStatus: bool = Field(None, alias="compound.package.reviewed")
|
|
||||||
|
|
||||||
|
|
||||||
class CompoundStructureSchema(Schema):
|
class CompoundStructureSchema(Schema):
|
||||||
InChI: str = Field(None, alias="inchi")
|
InChI: str = Field(None, alias="inchi")
|
||||||
aliases: List[str] = Field([], alias="aliases")
|
aliases: List[str] = Field([], alias="aliases")
|
||||||
@ -260,8 +421,6 @@ class CompoundStructureSchema(Schema):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def resolve_charge(obj: CompoundStructure):
|
def resolve_charge(obj: CompoundStructure):
|
||||||
print(obj.smiles)
|
|
||||||
print(FormatConverter.charge(obj.smiles))
|
|
||||||
return FormatConverter.charge(obj.smiles)
|
return FormatConverter.charge(obj.smiles)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -302,10 +461,11 @@ class CompoundStructureWrapper(Schema):
|
|||||||
|
|
||||||
@router.get("/compound", response={200: CompoundWrapper, 403: Error})
|
@router.get("/compound", response={200: CompoundWrapper, 403: Error})
|
||||||
def get_compounds(request):
|
def get_compounds(request):
|
||||||
qs = Compound.objects.none()
|
return {
|
||||||
for p in PackageManager.get_reviewed_packages():
|
'compound': Compound.objects.filter(
|
||||||
qs |= Compound.objects.filter(package=p)
|
package__in=PackageManager.get_reviewed_packages()
|
||||||
return {'compound': qs}
|
).prefetch_related('package')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/package/{uuid:package_uuid}/compound", response={200: CompoundWrapper, 403: Error})
|
@router.get("/package/{uuid:package_uuid}/compound", response={200: CompoundWrapper, 403: Error})
|
||||||
@ -354,14 +514,6 @@ def get_package_compound_structure(request, package_uuid, compound_uuid, structu
|
|||||||
#########
|
#########
|
||||||
# Rules #
|
# Rules #
|
||||||
#########
|
#########
|
||||||
class SimpleRule(SimpleObject):
|
|
||||||
identifier: str = 'rule'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def resolve_url(obj: Rule):
|
|
||||||
return obj.url.replace('-ambit-', '-').replace('-rdkit-', '-')
|
|
||||||
|
|
||||||
|
|
||||||
class RuleWrapper(Schema):
|
class RuleWrapper(Schema):
|
||||||
rule: List['SimpleRule']
|
rule: List['SimpleRule']
|
||||||
|
|
||||||
@ -469,10 +621,11 @@ class CompositeRuleSchema(Schema):
|
|||||||
|
|
||||||
@router.get("/rule", response={200: RuleWrapper, 403: Error})
|
@router.get("/rule", response={200: RuleWrapper, 403: Error})
|
||||||
def get_rules(request):
|
def get_rules(request):
|
||||||
qs = Rule.objects.none()
|
return {
|
||||||
for p in PackageManager.get_reviewed_packages():
|
'rule': Rule.objects.filter(
|
||||||
qs |= Rule.objects.filter(package=p)
|
package__in=PackageManager.get_reviewed_packages()
|
||||||
return {'rule': qs}
|
).prefetch_related('package')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/package/{uuid:package_uuid}/rule", response={200: RuleWrapper, 403: Error})
|
@router.get("/package/{uuid:package_uuid}/rule", response={200: RuleWrapper, 403: Error})
|
||||||
@ -556,10 +709,6 @@ def _post_package_rule(request, package_uuid, rule_uuid, compound: Form[str]):
|
|||||||
############
|
############
|
||||||
# Reaction #
|
# Reaction #
|
||||||
############
|
############
|
||||||
class SimpleReaction(SimpleObject):
|
|
||||||
identifier: str = 'reaction'
|
|
||||||
|
|
||||||
|
|
||||||
class ReactionWrapper(Schema):
|
class ReactionWrapper(Schema):
|
||||||
reaction: List['SimpleReaction']
|
reaction: List['SimpleReaction']
|
||||||
|
|
||||||
@ -613,10 +762,11 @@ class ReactionSchema(Schema):
|
|||||||
|
|
||||||
@router.get("/reaction", response={200: ReactionWrapper, 403: Error})
|
@router.get("/reaction", response={200: ReactionWrapper, 403: Error})
|
||||||
def get_reactions(request):
|
def get_reactions(request):
|
||||||
qs = Reaction.objects.none()
|
return {
|
||||||
for p in PackageManager.get_reviewed_packages():
|
'reaction': Reaction.objects.filter(
|
||||||
qs |= Reaction.objects.filter(package=p)
|
package__in=PackageManager.get_reviewed_packages()
|
||||||
return {'reaction': qs}
|
).prefetch_related('package')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/package/{uuid:package_uuid}/reaction", response={200: ReactionWrapper, 403: Error})
|
@router.get("/package/{uuid:package_uuid}/reaction", response={200: ReactionWrapper, 403: Error})
|
||||||
@ -642,10 +792,6 @@ def get_package_reaction(request, package_uuid, reaction_uuid):
|
|||||||
############
|
############
|
||||||
# Scenario #
|
# Scenario #
|
||||||
############
|
############
|
||||||
class SimpleScenario(SimpleObject):
|
|
||||||
identifier: str = 'scenario'
|
|
||||||
|
|
||||||
|
|
||||||
class ScenarioWrapper(Schema):
|
class ScenarioWrapper(Schema):
|
||||||
scenario: List['SimpleScenario']
|
scenario: List['SimpleScenario']
|
||||||
|
|
||||||
@ -676,10 +822,11 @@ class ScenarioSchema(Schema):
|
|||||||
|
|
||||||
@router.get("/scenario", response={200: ScenarioWrapper, 403: Error})
|
@router.get("/scenario", response={200: ScenarioWrapper, 403: Error})
|
||||||
def get_scenarios(request):
|
def get_scenarios(request):
|
||||||
qs = Scenario.objects.none()
|
return {
|
||||||
for p in PackageManager.get_reviewed_packages():
|
'scenario': Scenario.objects.filter(
|
||||||
qs |= Scenario.objects.filter(package=p)
|
package__in=PackageManager.get_reviewed_packages()
|
||||||
return {'scenario': qs}
|
).prefetch_related('package')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/package/{uuid:package_uuid}/scenario", response={200: ScenarioWrapper, 403: Error})
|
@router.get("/package/{uuid:package_uuid}/scenario", response={200: ScenarioWrapper, 403: Error})
|
||||||
@ -705,18 +852,112 @@ def get_package_scenario(request, package_uuid, scenario_uuid):
|
|||||||
###########
|
###########
|
||||||
# Pathway #
|
# Pathway #
|
||||||
###########
|
###########
|
||||||
class SimplePathway(SimpleObject):
|
|
||||||
identifier: str = 'pathway'
|
|
||||||
|
|
||||||
class PathwayWrapper(Schema):
|
class PathwayWrapper(Schema):
|
||||||
pathway: List['SimplePathway']
|
pathway: List['SimplePathway']
|
||||||
|
|
||||||
|
class PathwayEdge(Schema):
|
||||||
|
ecNumbers: List[str] = Field([], alias="ec_numbers")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
idreaction: str = Field(None, alias="edge_label.url")
|
||||||
|
multstep: bool = Field(None, alias="edge_label.multi_step")
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
pseudo: bool = False
|
||||||
|
rule: Optional[str] = Field(None, alias="rule")
|
||||||
|
scenarios: List[SimpleScenario] = Field([], alias="scenarios")
|
||||||
|
source: int = -1
|
||||||
|
target: int = -1
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_rule(obj: Edge):
|
||||||
|
if obj.edge_label.rules.all().exists():
|
||||||
|
r = obj.edge_label.rules.all()[0]
|
||||||
|
if isinstance(r, SimpleAmbitRule):
|
||||||
|
return r.smirks
|
||||||
|
return None
|
||||||
|
|
||||||
|
class PathwayNode(Schema):
|
||||||
|
atomCount: int = Field(None, alias="atom_count")
|
||||||
|
depth: int = Field(None, alias="depth")
|
||||||
|
dt50s: List[Dict[str, str]] = Field([], alias="dt50s")
|
||||||
|
engineeredIntermediate: bool = Field(None, alias="engineered_intermediate")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
idcomp: str = Field(None, alias="default_node_label.url")
|
||||||
|
idreact: str = Field(None, alias="default_node_label.url")
|
||||||
|
image: str = Field(None, alias="image")
|
||||||
|
imageSize: int = Field(None, alias="image_size")
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
proposed: List[Dict[str, str]] = Field([], alias="proposed_intermediate")
|
||||||
|
smiles: str = Field(None, alias="default_node_label.smiles")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_atom_count(obj: Node):
|
||||||
|
from rdkit import Chem
|
||||||
|
return Chem.MolFromSmiles(obj.default_node_label.smiles).GetNumAtoms()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_dt50s(obj: Node):
|
||||||
|
# TODO
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_engineered_intermediate(obj: Node):
|
||||||
|
# TODO
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_image(obj: Node):
|
||||||
|
return f"{obj.default_node_label.url}?image=svg"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_image_size(obj: Node):
|
||||||
|
return 400
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_proposed_intermediate(obj: Node):
|
||||||
|
# TODO
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class PathwaySchema(Schema):
|
||||||
|
aliases: List[str] = Field([], alias="aliases")
|
||||||
|
completed: str = Field(None, alias="completed")
|
||||||
|
description: str = Field(None, alias="description")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
isIncremental: bool = Field(None, alias="is_incremental")
|
||||||
|
isPredicted: bool = Field(None, alias="is_predicted")
|
||||||
|
lastModified: int = Field(None, alias="last_modified")
|
||||||
|
links: List[PathwayEdge] = Field([], alias="edges")
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
nodes: List[PathwayNode] = Field([], alias="nodes")
|
||||||
|
pathwayName: str = Field(None, alias="name")
|
||||||
|
reviewStatus: str = Field(None, alias="review_status")
|
||||||
|
scenarios: List['SimpleScenario'] = Field([], alias="scenarios")
|
||||||
|
upToDate: bool = Field(None, alias="up_to_date")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_review_status(obj: Pathway):
|
||||||
|
return 'reviewed' if obj.package.reviewed else 'unreviewed'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_completed(obj: Pathway):
|
||||||
|
return str(obj.completed()).lower()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_up_to_date(obj: Pathway):
|
||||||
|
return "true"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_last_modified(obj: Pathway):
|
||||||
|
return int(obj.modified.timestamp())
|
||||||
|
|
||||||
|
|
||||||
@router.get("/pathway", response={200: PathwayWrapper, 403: Error})
|
@router.get("/pathway", response={200: PathwayWrapper, 403: Error})
|
||||||
def get_pathways(request):
|
def get_pathways(request):
|
||||||
qs = Pathway.objects.none()
|
return {
|
||||||
for p in PackageManager.get_reviewed_packages():
|
'pathway': Pathway.objects.filter(
|
||||||
qs |= Pathway.objects.filter(package=p)
|
package__in=PackageManager.get_reviewed_packages()
|
||||||
return {'pathway': qs}
|
).prefetch_related('package')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/package/{uuid:package_uuid}/pathway", response={200: PathwayWrapper, 403: Error})
|
@router.get("/package/{uuid:package_uuid}/pathway", response={200: PathwayWrapper, 403: Error})
|
||||||
@ -729,11 +970,217 @@ def get_package_pathways(request, package_uuid):
|
|||||||
'message': f'Getting Pathways for Package with id {package_uuid} failed due to insufficient rights!'}
|
'message': f'Getting Pathways for Package with id {package_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
# @router.get("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}", response={200: Pathway, 403: Error})
|
@router.get("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}", response={200: PathwaySchema, 403: Error})
|
||||||
# def get_package_pathway(request, package_uuid, pathway_uuid):
|
def get_package_pathway(request, package_uuid, pathway_uuid):
|
||||||
# try:
|
try:
|
||||||
# p = PackageManager.get_package_by_id(request.user, package_uuid)
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
# return Pathway.objects.get(package=p, uuid=pathway_uuid)
|
return Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||||
# except ValueError:
|
except ValueError:
|
||||||
# return 403, {
|
return 403, {
|
||||||
# 'message': f'Getting Pathway with id {pathway_uuid} failed due to insufficient rights!'}
|
'message': f'Getting Pathway with id {pathway_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/package/{uuid:package_uuid}/pathway")
|
||||||
|
def create_pathway(
|
||||||
|
request,
|
||||||
|
package_uuid,
|
||||||
|
smilesinput: Form[str],
|
||||||
|
name: Optional[str] = Form(None),
|
||||||
|
description: Optional[str] = Form(None),
|
||||||
|
rootOnly: Optional[str] = Form(None),
|
||||||
|
selectedSetting: Optional[str] = Form(None)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
|
|
||||||
|
stand_smiles = FormatConverter.standardize(smilesinput.strip())
|
||||||
|
|
||||||
|
pw = Pathway.create(p, stand_smiles, name=name, description=description)
|
||||||
|
|
||||||
|
pw_mode = 'predict'
|
||||||
|
if rootOnly and rootOnly == 'true':
|
||||||
|
pw_mode = 'build'
|
||||||
|
|
||||||
|
pw.kv.update({'mode': pw_mode})
|
||||||
|
pw.save()
|
||||||
|
|
||||||
|
if pw_mode == 'predict':
|
||||||
|
setting = request.user.prediction_settings()
|
||||||
|
|
||||||
|
if selectedSetting:
|
||||||
|
setting = SettingManager.get_setting_by_url(request.user, selectedSetting)
|
||||||
|
|
||||||
|
pw.setting = setting
|
||||||
|
pw.save()
|
||||||
|
|
||||||
|
from .tasks import predict
|
||||||
|
predict.delay(pw.pk, setting.pk, limit=-1)
|
||||||
|
|
||||||
|
return redirect(pw.url)
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
########
|
||||||
|
# Node #
|
||||||
|
########
|
||||||
|
class NodeWrapper(Schema):
|
||||||
|
node: List['SimpleNode']
|
||||||
|
|
||||||
|
class NodeCompoundStructure(Schema):
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
image: str = Field(None, alias="image")
|
||||||
|
smiles: str = Field(None, alias="smiles")
|
||||||
|
name:str =Field(None, alias="name")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_image(obj: CompoundStructure):
|
||||||
|
return f"{obj.url}?image=svg"
|
||||||
|
|
||||||
|
class NodeSchema(Schema):
|
||||||
|
aliases: List[str] = Field([], alias="aliases")
|
||||||
|
confidenceScenarios: List[SimpleScenario] = Field([], alias="confidence_scenarios")
|
||||||
|
defaultStructure: NodeCompoundStructure = Field(None, alias="default_node_label")
|
||||||
|
depth: int = Field(None, alias="depth")
|
||||||
|
description: str = Field(None, alias="description")
|
||||||
|
engineeredIntermediate:bool = Field(None, alias="engineered_intermediate")
|
||||||
|
halflifes: Dict[str, str] = Field({}, alias="halflife")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
identifier: str = 'node'
|
||||||
|
image: str = Field(None, alias="image")
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
proposedValues: List[Dict[str, str]] = Field([], alias="proposed_values")
|
||||||
|
reviewStatus: str = Field(None, alias="review_status")
|
||||||
|
scenarios: List['SimpleScenario'] = Field([], alias="scenarios")
|
||||||
|
smiles: str = Field(None, alias="default_node_label.smiles")
|
||||||
|
structures: List['CompoundStructureSchema'] = Field([], alias="node_labels")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_engineered_intermediate(obj: Node):
|
||||||
|
# TODO
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_image(obj: Node):
|
||||||
|
return f"{obj.default_node_label.url}?image=svg"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_proposed_values(obj: Node):
|
||||||
|
# TODO
|
||||||
|
# {
|
||||||
|
# "scenarioId": "https://envipath.org/package/5882df9c-dae1-4d80-a40e-db4724271456/scenario/1f1a0b67-ce57-4f5a-929c-4fabf3a791fd",
|
||||||
|
# "scenarioName": "Annex IIA 7.1.1 a), Brumhard (2003) - (00000)"
|
||||||
|
# }
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_review_status(obj: Node):
|
||||||
|
return 'reviewed' if obj.pathway.package.reviewed else 'unreviewed'
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/node", response={200: NodeWrapper, 403: Error})
|
||||||
|
def get_package_pathway_nodes(request, package_uuid, pathway_uuid):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
|
return {'node': Pathway.objects.get(package=p, uuid=pathway_uuid).nodes}
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
'message': f'Getting Nodes for Pathway with id {pathway_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/node/{uuid:node_uuid}", response={200: NodeSchema, 403: Error})
|
||||||
|
def get_package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
|
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||||
|
return Node.objects.get(pathway=pw, uuid=node_uuid)
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
'message': f'Getting Node with id {node_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
########
|
||||||
|
# Edge #
|
||||||
|
########
|
||||||
|
class EdgeWrapper(Schema):
|
||||||
|
edge: List['SimpleEdge']
|
||||||
|
|
||||||
|
class EdgeNode(SimpleNode):
|
||||||
|
image: str = Field(None, alias="image")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_image(obj: Node):
|
||||||
|
return f"{obj.default_node_label.url}?image=svg"
|
||||||
|
|
||||||
|
class EdgeSchema(Schema):
|
||||||
|
aliases: List[str] = Field([], alias="aliases")
|
||||||
|
description: str = Field(None, alias="description")
|
||||||
|
ecNumbers: List[str] = Field([], alias="ec_numbers")
|
||||||
|
endNodes: List['EdgeNode'] = Field([], alias="end_nodes")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
identifier: str = 'edge'
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
reactionName: str = Field(None, alias="edge_label.name")
|
||||||
|
reactionURI: str = Field(None, alias="edge_label.url")
|
||||||
|
reviewStatus: str = Field(None, alias="review_status")
|
||||||
|
scenarios: List['SimpleScenario'] = Field([], alias="scenarios")
|
||||||
|
startNodes: List['EdgeNode'] = Field([], alias="start_nodes")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_review_status(obj: Node):
|
||||||
|
return 'reviewed' if obj.pathway.package.reviewed else 'unreviewed'
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/edge", response={200: EdgeWrapper, 403: Error})
|
||||||
|
def get_package_pathway_edges(request, package_uuid, pathway_uuid):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
|
return {'edge': Pathway.objects.get(package=p, uuid=pathway_uuid).edges}
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
'message': f'Getting Edges for Pathway with id {pathway_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/edge/{uuid:edge_uuid}", response={200: EdgeSchema, 403: Error})
|
||||||
|
def get_package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||||
|
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||||
|
return Edge.objects.get(pathway=pw, uuid=edge_uuid)
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
'message': f'Getting Edge with id {edge_uuid} failed due to insufficient rights!'}
|
||||||
|
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Setting #
|
||||||
|
###########
|
||||||
|
class SettingWrapper(Schema):
|
||||||
|
setting: List['SimpleSetting']
|
||||||
|
|
||||||
|
|
||||||
|
class SettingSchema(Schema):
|
||||||
|
duplicationHash: int = -1
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
identifier: str = 'setting'
|
||||||
|
includedPackages: List['SimplePackage'] = Field([], alias="rule_packages")
|
||||||
|
isPublic: bool = Field(None, alias="public")
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
normalizationRules: List['SimpleRule']= Field([], alias="normalization_rules")
|
||||||
|
propertyPlugins: List[str] = Field([], alias="property_plugins")
|
||||||
|
truncationstrategy: Optional[str] = Field(None, alias="truncation_strategy")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/setting', response={200: SettingWrapper, 403: Error})
|
||||||
|
def get_settings(request):
|
||||||
|
return {
|
||||||
|
'setting': SettingManager.get_all_settings(request.user)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/setting/{uuid:setting_uuid}', response={200: SettingSchema, 403: Error})
|
||||||
|
def get_setting(request, setting_uuid):
|
||||||
|
try:
|
||||||
|
return SettingManager.get_setting_by_id(request.user, setting_uuid)
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
'message': f'Getting Setting with id {setting_uuid} failed due to insufficient rights!'}
|
||||||
|
|||||||
@ -1402,13 +1402,13 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin):
|
|||||||
|
|
||||||
# Mode
|
# Mode
|
||||||
def is_built(self):
|
def is_built(self):
|
||||||
return self.kv.get('mode', 'build') == 'predicted'
|
return self.kv.get('mode', 'build') == 'build'
|
||||||
|
|
||||||
def is_predicted(self):
|
def is_predicted(self):
|
||||||
return self.kv.get('mode', 'build') == 'predicted'
|
return self.kv.get('mode', 'build') == 'predicted'
|
||||||
|
|
||||||
def is_predicted(self):
|
def is_incremental(self):
|
||||||
return self.kv.get('mode', 'build') == 'predicted'
|
return self.kv.get('mode', 'build') == 'incremental'
|
||||||
|
|
||||||
# Status
|
# Status
|
||||||
def status(self):
|
def status(self):
|
||||||
|
|||||||
@ -751,7 +751,7 @@ function handleAssessmentResponse(depict_url, data) {
|
|||||||
var predProb = "<a class='list-group-item'>Predicted probability: " + transObj['probability'].toFixed(2) + "</a>";
|
var predProb = "<a class='list-group-item'>Predicted probability: " + transObj['probability'].toFixed(2) + "</a>";
|
||||||
var timesTriggered = "<a class='list-group-item'>This rule has triggered " + transObj['times_triggered'] + " times in the training set</a>";
|
var timesTriggered = "<a class='list-group-item'>This rule has triggered " + transObj['times_triggered'] + " times in the training set</a>";
|
||||||
var reliability = "<a class='list-group-item'>Reliability: " + transObj['reliability'].toFixed(2) + " (" + (transObj['reliability'] > data['ad_params']['reliability_threshold'] ? ">" : "<") + " Reliability Threshold of " + data['ad_params']['reliability_threshold'] + ") </a>";
|
var reliability = "<a class='list-group-item'>Reliability: " + transObj['reliability'].toFixed(2) + " (" + (transObj['reliability'] > data['ad_params']['reliability_threshold'] ? ">" : "<") + " Reliability Threshold of " + data['ad_params']['reliability_threshold'] + ") </a>";
|
||||||
var localCompatibility = "<a class='list-group-item'>Local Compatibility: " + transObj['local_compatibility'].toFixed(2) + " (" + (transObj['local_compatibility'] > data['ad_params']['local_compatibilty_threshold'] ? ">" : "<") + " Local Compatibility Threshold of " + data['ad_params']['local_compatibilty_threshold'] + ")</a>";
|
var localCompatibility = "<a class='list-group-item'>Local Compatibility: " + transObj['local_compatibility'].toFixed(2) + " (" + (transObj['local_compatibility'] > data['ad_params']['local_compatibility_threshold'] ? ">" : "<") + " Local Compatibility Threshold of " + data['ad_params']['local_compatibility_threshold'] + ")</a>";
|
||||||
|
|
||||||
var transImg = "<img width='100%' src='" + transObj['rule']['url'] + "?smiles=" + encodeURIComponent(data['assessment']['smiles']) + "'>";
|
var transImg = "<img width='100%' src='" + transObj['rule']['url'] + "?smiles=" + encodeURIComponent(data['assessment']['smiles']) + "'>";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user