forked from enviPath/enviPy
[Feature] Legacy API (#224)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#224
This commit is contained in:
@ -1,18 +1,21 @@
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import nh3
|
||||
from django.conf import settings as s
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
from ninja import Field, Form, Router, Schema
|
||||
from ninja import Field, Form, Router, Schema, Query
|
||||
|
||||
from utilities.chem import FormatConverter
|
||||
from utilities.misc import PackageExporter
|
||||
|
||||
from .logic import PackageManager, SettingManager, UserManager
|
||||
from .logic import GroupManager, PackageManager, SettingManager, UserManager
|
||||
from .models import (
|
||||
Compound,
|
||||
CompoundStructure,
|
||||
Edge,
|
||||
EPModel,
|
||||
Node,
|
||||
Pathway,
|
||||
Reaction,
|
||||
@ -21,6 +24,7 @@ from .models import (
|
||||
SimpleAmbitRule,
|
||||
User,
|
||||
UserPackagePermission,
|
||||
ParallelRule,
|
||||
)
|
||||
|
||||
Package = s.GET_PACKAGE_MODEL()
|
||||
@ -121,6 +125,10 @@ class SimpleEdge(SimpleObject):
|
||||
identifier: str = "edge"
|
||||
|
||||
|
||||
class SimpleModel(SimpleObject):
|
||||
identifier: str = "relative-reasoning"
|
||||
|
||||
|
||||
################
|
||||
# Login/Logout #
|
||||
################
|
||||
@ -169,9 +177,13 @@ class UserSchema(Schema):
|
||||
return SettingManager.get_all_settings(obj)
|
||||
|
||||
|
||||
class Me(Schema):
|
||||
whoami: str | None = None
|
||||
|
||||
|
||||
@router.get("/user", response={200: UserWrapper, 403: Error})
|
||||
def get_users(request, whoami: str = None):
|
||||
if whoami:
|
||||
def get_users(request, me: Query[Me]):
|
||||
if me.whoami:
|
||||
return {"user": [request.user]}
|
||||
else:
|
||||
return {"user": User.objects.all()}
|
||||
@ -253,67 +265,110 @@ def get_packages(request):
|
||||
}
|
||||
|
||||
|
||||
@router.get("/package/{uuid:package_uuid}", response={200: PackageSchema, 403: Error})
|
||||
def get_package(request, package_uuid):
|
||||
class GetPackage(Schema):
|
||||
exportAsJson: str | None = None
|
||||
|
||||
|
||||
@router.get("/package/{uuid:package_uuid}", response={200: PackageSchema | Any, 403: Error})
|
||||
def get_package(request, package_uuid, gp: Query[GetPackage]):
|
||||
try:
|
||||
return PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if gp.exportAsJson and gp.exportAsJson.strip() == "true":
|
||||
return PackageExporter(p).do_export()
|
||||
|
||||
return p
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Getting Package with id {package_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
class CreatePackage(Schema):
|
||||
packageName: str
|
||||
packageDescription: str | None = None
|
||||
|
||||
|
||||
@router.post("/package")
|
||||
def create_packages(
|
||||
request, packageName: Form[str], packageDescription: Optional[str] = Form(None)
|
||||
request,
|
||||
p: Form[CreatePackage],
|
||||
):
|
||||
try:
|
||||
if packageName.strip() == "":
|
||||
if p.packageName.strip() == "":
|
||||
raise ValueError("Package name cannot be empty!")
|
||||
|
||||
new_pacakge = PackageManager.create_package(request.user, packageName, packageDescription)
|
||||
new_pacakge = PackageManager.create_package(
|
||||
request.user, p.packageName, p.packageDescription
|
||||
)
|
||||
return redirect(new_pacakge.url)
|
||||
except ValueError as e:
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
class UpdatePackage(Schema):
|
||||
packageDescription: str | None = None
|
||||
hiddenMethod: str | None = None
|
||||
permissions: str | None = None
|
||||
ppsURI: str | None = None
|
||||
read: str | None = None
|
||||
write: str | None = None
|
||||
|
||||
|
||||
@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),
|
||||
):
|
||||
def update_package(request, package_uuid, pack: Form[UpdatePackage]):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if hiddenMethod:
|
||||
if hiddenMethod == "DELETE":
|
||||
if pack.hiddenMethod:
|
||||
if pack.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
|
||||
elif pack.packageDescription is not None:
|
||||
description = nh3.clean(pack.packageDescription, tags=s.ALLOWED_HTML_TAGS).strip()
|
||||
|
||||
if description:
|
||||
p.description = description
|
||||
p.save()
|
||||
return HttpResponse(status=200)
|
||||
else:
|
||||
raise ValueError("Package description cannot be empty!")
|
||||
elif all([pack.permissions, pack.ppsURI, pack.read]):
|
||||
if "group" in pack.ppsURI:
|
||||
grantee = GroupManager.get_group_lp(pack.ppsURI)
|
||||
else:
|
||||
grantee = UserManager.get_user_lp(pack.ppsURI)
|
||||
|
||||
PackageManager.grant_read(request.user, p, grantee)
|
||||
return HttpResponse(status=200)
|
||||
elif all([pack.permissions, pack.ppsURI, pack.write]):
|
||||
if "group" in pack.ppsURI:
|
||||
grantee = GroupManager.get_group_lp(pack.ppsURI)
|
||||
else:
|
||||
grantee = UserManager.get_user_lp(pack.ppsURI)
|
||||
|
||||
PackageManager.grant_write(request.user, p, grantee)
|
||||
return HttpResponse(status=200)
|
||||
except ValueError as e:
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}")
|
||||
def delete_package(request, package_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.administrable(request.user, p):
|
||||
p.delete()
|
||||
return redirect(f"{s.SERVER_URL}/package")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Package!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Package with id {package_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
################################
|
||||
# Compound / CompoundStructure #
|
||||
################################
|
||||
@ -511,6 +566,83 @@ def get_package_compound_structure(request, package_uuid, compound_uuid, structu
|
||||
}
|
||||
|
||||
|
||||
class CreateCompound(Schema):
|
||||
compoundSmiles: str
|
||||
compoundName: str | None = None
|
||||
compoundDescription: str | None = None
|
||||
inchi: str | None = None
|
||||
|
||||
|
||||
@router.post("/package/{uuid:package_uuid}/compound")
|
||||
def create_package_compound(
|
||||
request,
|
||||
package_uuid,
|
||||
c: Form[CreateCompound],
|
||||
):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
# inchi is not used atm
|
||||
c = Compound.create(
|
||||
p, c.compoundSmiles, c.compoundName, c.compoundDescription, inchi=c.inchi
|
||||
)
|
||||
return redirect(c.url)
|
||||
except ValueError as e:
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/compound/{uuid:compound_uuid}")
|
||||
def delete_compound(request, package_uuid, compound_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
c = Compound.objects.get(package=p, uuid=compound_uuid)
|
||||
c.delete()
|
||||
return redirect(f"{p.url}/compound")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Compound!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Compound with id {compound_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/package/{uuid:package_uuid}/compound/{uuid:compound_uuid}/structure/{uuid:structure_uuid}"
|
||||
)
|
||||
def delete_compound_structure(request, package_uuid, compound_uuid, structure_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
c = Compound.objects.get(package=p, uuid=compound_uuid)
|
||||
cs = CompoundStructure.objects.get(compound=c, uuid=structure_uuid)
|
||||
|
||||
# Check if we have to delete the compound as no structure is left
|
||||
if len(cs.compound.structures.all()) == 1:
|
||||
# This will delete the structure as well
|
||||
c.delete()
|
||||
return redirect(p.url + "/compound")
|
||||
else:
|
||||
if cs.normalized_structure:
|
||||
c.delete()
|
||||
return redirect(p.url + "/compound")
|
||||
else:
|
||||
if c.default_structure == cs:
|
||||
cs.delete()
|
||||
c.default_structure = c.structures.all().first()
|
||||
return redirect(c.url + "/structure")
|
||||
else:
|
||||
cs.delete()
|
||||
return redirect(c.url + "/structure")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this CompoundStructure!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting CompoundStructure with id {compound_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
#########
|
||||
# Rules #
|
||||
#########
|
||||
@ -674,6 +806,73 @@ def _get_package_rule(request, package_uuid, rule_uuid):
|
||||
|
||||
|
||||
# POST
|
||||
class CreateSimpleRule(Schema):
|
||||
smirks: str
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
reactantFilterSmarts: str | None = None
|
||||
productFilterSmarts: str | None = None
|
||||
immediate: str | None = None
|
||||
rdkitrule: str | None = None
|
||||
|
||||
|
||||
@router.post("/package/{uuid:package_uuid}/simple-rule")
|
||||
def create_package_simple_rule(
|
||||
request,
|
||||
package_uuid,
|
||||
r: Form[CreateSimpleRule],
|
||||
):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if r.rdkitrule and r.rdkitrule.strip() == "true":
|
||||
raise ValueError("Not yet implemented!")
|
||||
else:
|
||||
sr = SimpleAmbitRule.create(
|
||||
p, r.name, r.description, r.smirks, r.reactantFilterSmarts, r.productFilterSmarts
|
||||
)
|
||||
|
||||
return redirect(sr.url)
|
||||
|
||||
except ValueError as e:
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
class CreateParallelRule(Schema):
|
||||
simpleRules: str
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
reactantFilterSmarts: str | None = None
|
||||
productFilterSmarts: str | None = None
|
||||
immediate: str | None = None
|
||||
|
||||
|
||||
@router.post("/package/{uuid:package_uuid}/parallel-rule")
|
||||
def create_package_parallel_rule(
|
||||
request,
|
||||
package_uuid,
|
||||
r: Form[CreateParallelRule],
|
||||
):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
srs = SimpleRule.objects.filter(package=p, url__in=r.simpleRules)
|
||||
|
||||
if srs.count() != len(r.simpleRules):
|
||||
raise ValueError(
|
||||
f"Not all SimpleRules could be found in Package with id {package_uuid}!"
|
||||
)
|
||||
|
||||
sr = ParallelRule.create(
|
||||
p, list(srs), r.name, r.description, r.reactantFilterSmarts, r.productFilterSmarts
|
||||
)
|
||||
|
||||
return redirect(sr.url)
|
||||
|
||||
except ValueError as e:
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
@router.post(
|
||||
"/package/{uuid:package_uuid}/rule/{uuid:rule_uuid}", response={200: str | Any, 403: Error}
|
||||
)
|
||||
@ -723,6 +922,41 @@ def _post_package_rule(request, package_uuid, rule_uuid, compound: Form[str]):
|
||||
}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/rule/{uuid:rule_uuid}")
|
||||
def delete_rule(request, package_uuid, rule_uuid):
|
||||
return _delete_rule(request, package_uuid, rule_uuid)
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/package/{uuid:package_uuid}/simple-rule/{uuid:rule_uuid}",
|
||||
)
|
||||
def delete_simple_rule(request, package_uuid, rule_uuid):
|
||||
return _delete_rule(request, package_uuid, rule_uuid)
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/package/{uuid:package_uuid}/parallel-rule/{uuid:rule_uuid}",
|
||||
)
|
||||
def delete_parallel_rule(request, package_uuid, rule_uuid):
|
||||
return _delete_rule(request, package_uuid, rule_uuid)
|
||||
|
||||
|
||||
def _delete_rule(request, package_uuid, rule_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
r = Rule.objects.get(package=p, uuid=rule_uuid)
|
||||
r.delete()
|
||||
return redirect(f"{p.url}/rule")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Rule!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Rule with id {rule_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
############
|
||||
# Reaction #
|
||||
############
|
||||
@ -811,6 +1045,82 @@ def get_package_reaction(request, package_uuid, reaction_uuid):
|
||||
}
|
||||
|
||||
|
||||
class CreateReaction(Schema):
|
||||
reactionName: str | None = None
|
||||
reactionDescription: str | None = None
|
||||
smirks: str | None = None
|
||||
educt: str | None = None
|
||||
product: str | None = None
|
||||
rule: str | None = None
|
||||
|
||||
|
||||
@router.post("/package/{uuid:package_uuid}/reaction")
|
||||
def create_package_reaction(
|
||||
request,
|
||||
package_uuid,
|
||||
r: Form[CreateReaction],
|
||||
):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if r.smirks is None and (r.educt is None or r.product is None):
|
||||
raise ValueError("Either SMIRKS or educt/product must be provided")
|
||||
|
||||
if r.smirks is not None and (r.educt is not None and r.product is not None):
|
||||
raise ValueError("SMIRKS and educt/product provided!")
|
||||
|
||||
rule = None
|
||||
if r.rule:
|
||||
try:
|
||||
rule = Rule.objects.get(package=p, url=r.rule)
|
||||
except Rule.DoesNotExist:
|
||||
raise ValueError(f"Rule with id {r.rule} does not exist!")
|
||||
|
||||
if r.educt is not None:
|
||||
try:
|
||||
educt_cs = CompoundStructure.objects.get(compound__package=p, url=r.educt)
|
||||
except CompoundStructure.DoesNotExist:
|
||||
raise ValueError(f"Compound with id {r.educt} does not exist!")
|
||||
|
||||
try:
|
||||
product_cs = CompoundStructure.objects.get(compound__package=p, url=r.product)
|
||||
except CompoundStructure.DoesNotExist:
|
||||
raise ValueError(f"Compound with id {r.product} does not exist!")
|
||||
|
||||
new_r = Reaction.create(
|
||||
p, r.reactionName, r.reactionDescription, [educt_cs], [product_cs], rule
|
||||
)
|
||||
else:
|
||||
educts = r.smirks.split(">>")[0].split("\\.")
|
||||
products = r.smirks.split(">>")[1].split("\\.")
|
||||
|
||||
new_r = Reaction.create(
|
||||
p, r.reactionName, r.reactionDescription, educts, products, rule
|
||||
)
|
||||
|
||||
return redirect(new_r.url)
|
||||
|
||||
except ValueError as e:
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/reaction/{uuid:reaction_uuid}")
|
||||
def delete_reaction(request, package_uuid, reaction_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
r = Reaction.objects.get(package=p, uuid=reaction_uuid)
|
||||
r.delete()
|
||||
return redirect(f"{p.url}/reaction")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Reaction!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Reaction with id {reaction_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
############
|
||||
# Scenario #
|
||||
############
|
||||
@ -825,7 +1135,7 @@ class ScenarioSchema(Schema):
|
||||
description: str = Field(None, alias="description")
|
||||
id: str = Field(None, alias="url")
|
||||
identifier: str = "scenario"
|
||||
linkedTo: List[Dict[str, str]] = Field({}, alias="linked_to")
|
||||
linkedTo: List[Dict[str, str]] = Field([], alias="linked_to")
|
||||
name: str = Field(None, alias="name")
|
||||
pathways: List["SimplePathway"] = Field([], alias="related_pathways")
|
||||
relatedScenarios: List[Dict[str, str]] = Field([], alias="related_scenarios")
|
||||
@ -876,6 +1186,38 @@ def get_package_scenario(request, package_uuid, scenario_uuid):
|
||||
}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/scenario")
|
||||
def delete_scenarios(request, package_uuid, scenario_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
scens = Scenario.objects.filter(package=p)
|
||||
scens.delete()
|
||||
return redirect(f"{p.url}/scenario")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete Scenarios!")
|
||||
except ValueError:
|
||||
return 403, {"message": "Deleting Scenarios failed due to insufficient rights!"}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/scenario/{uuid:scenario_uuid}")
|
||||
def delete_scenario(request, package_uuid, scenario_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
scen = Scenario.objects.get(package=p, uuid=scenario_uuid)
|
||||
scen.delete()
|
||||
return redirect(f"{p.url}/scenario")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Scenario!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Scenario with id {scenario_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
###########
|
||||
# Pathway #
|
||||
###########
|
||||
@ -1015,46 +1357,67 @@ def get_package_pathway(request, package_uuid, pathway_uuid):
|
||||
}
|
||||
|
||||
|
||||
class CreatePathway(Schema):
|
||||
smilesinput: str
|
||||
name: str | None = None
|
||||
description: str | None = None
|
||||
rootOnly: str | None = None
|
||||
selectedSetting: str | None = None
|
||||
|
||||
|
||||
@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),
|
||||
pw: Form[CreatePathway],
|
||||
):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
stand_smiles = FormatConverter.standardize(smilesinput.strip())
|
||||
stand_smiles = FormatConverter.standardize(pw.smilesinput.strip())
|
||||
|
||||
pw = Pathway.create(p, stand_smiles, name=name, description=description)
|
||||
new_pw = Pathway.create(p, stand_smiles, name=pw.name, description=pw.description)
|
||||
|
||||
pw_mode = "predict"
|
||||
if rootOnly and rootOnly == "true":
|
||||
if pw.rootOnly and pw.rootOnly.strip() == "true":
|
||||
pw_mode = "build"
|
||||
|
||||
pw.kv.update({"mode": pw_mode})
|
||||
pw.save()
|
||||
new_pw.kv.update({"mode": pw_mode})
|
||||
new_pw.save()
|
||||
|
||||
if pw_mode == "predict":
|
||||
setting = request.user.prediction_settings()
|
||||
|
||||
if selectedSetting:
|
||||
setting = SettingManager.get_setting_by_url(request.user, selectedSetting)
|
||||
if pw.selectedSetting:
|
||||
setting = SettingManager.get_setting_by_url(request.user, pw.selectedSetting)
|
||||
|
||||
pw.setting = setting
|
||||
pw.save()
|
||||
new_pw.setting = setting
|
||||
new_pw.save()
|
||||
|
||||
from .tasks import predict
|
||||
from .tasks import dispatch, predict
|
||||
|
||||
predict.delay(pw.pk, setting.pk, limit=-1)
|
||||
dispatch(request.user, predict, new_pw.pk, setting.pk, limit=-1)
|
||||
|
||||
return redirect(pw.url)
|
||||
return redirect(new_pw.url)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
return 400, {"message": str(e)}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}")
|
||||
def delete_pathway(request, package_uuid, pathway_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||
pw.delete()
|
||||
return redirect(f"{p.url}/pathway")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this pathway!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Pathway with id {pathway_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
########
|
||||
@ -1145,6 +1508,52 @@ def get_package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
|
||||
}
|
||||
|
||||
|
||||
class CreateNode(Schema):
|
||||
nodeAsSmiles: str
|
||||
nodeName: str | None = None
|
||||
nodeReason: str | None = None
|
||||
nodeDepth: str | None = None
|
||||
|
||||
|
||||
@router.post(
|
||||
"/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/node",
|
||||
response={200: str | Any, 403: Error},
|
||||
)
|
||||
def add_pathway_node(request, package_uuid, pathway_uuid, n: Form[CreateNode]):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||
|
||||
if n.nodeDepth is not None and n.nodeDepth.strip() != "":
|
||||
node_depth = int(n.nodeDepth)
|
||||
else:
|
||||
node_depth = -1
|
||||
|
||||
n = Node.create(pw, n.nodeAsSmiles, node_depth, n.nodeName, n.nodeReason)
|
||||
|
||||
return redirect(n.url)
|
||||
except ValueError:
|
||||
return 403, {"message": "Adding node failed!"}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/node/{uuid:node_uuid}")
|
||||
def delete_node(request, package_uuid, pathway_uuid, node_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||
n = Node.objects.get(pathway=pw, uuid=node_uuid)
|
||||
n.delete()
|
||||
return redirect(f"{pw.url}/node")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Node!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Node with id {node_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
########
|
||||
# Edge #
|
||||
########
|
||||
@ -1208,6 +1617,200 @@ def get_package_pathway_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||
}
|
||||
|
||||
|
||||
class CreateEdge(Schema):
|
||||
edgeAsSmirks: str | None = None
|
||||
educts: str | None = None # Node URIs comma sep
|
||||
products: str | None = None # Node URIs comma sep
|
||||
multistep: str | None = None
|
||||
edgeReason: str | None = None
|
||||
|
||||
|
||||
@router.post(
|
||||
"/package/{uuid:package_uuid}/üathway/{uuid:pathway_uuid}/edge",
|
||||
response={200: str | Any, 403: Error},
|
||||
)
|
||||
def add_pathway_edge(request, package_uuid, pathway_uuid, e: Form[CreateEdge]):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||
|
||||
if e.edgeAsSmirks is None and (e.educts is None or e.products is None):
|
||||
raise ValueError("Either SMIRKS or educt/product must be provided")
|
||||
|
||||
if e.edgeAsSmirks is not None and (e.educts is not None and e.products is not None):
|
||||
raise ValueError("SMIRKS and educt/product provided!")
|
||||
|
||||
educts = []
|
||||
products = []
|
||||
|
||||
if e.edgeAsSmirks:
|
||||
for ed in e.edgeAsSmirks.split(">>")[0].split("\\."):
|
||||
educts.append(Node.objects.get(pathway=pw, default_node_label__smiles=ed))
|
||||
|
||||
for pr in e.edgeAsSmirks.split(">>")[1].split("\\."):
|
||||
products.append(Node.objects.get(pathway=pw, default_node_label__smiles=pr))
|
||||
else:
|
||||
for ed in e.educts.split(","):
|
||||
educts.append(Node.objects.get(pathway=pw, url=ed.strip()))
|
||||
|
||||
for pr in e.products.split(","):
|
||||
products.append(Node.objects.get(pathway=pw, url=pr.strip()))
|
||||
|
||||
new_e = Edge.create(
|
||||
pathway=pw,
|
||||
start_nodes=educts,
|
||||
end_nodes=products,
|
||||
rule=None,
|
||||
name=e.name,
|
||||
description=e.edgeReason,
|
||||
)
|
||||
|
||||
return redirect(new_e.url)
|
||||
except ValueError:
|
||||
return 403, {"message": "Adding node failed!"}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/pathway/{uuid:pathway_uuid}/edge/{uuid:edge_uuid}")
|
||||
def delete_edge(request, package_uuid, pathway_uuid, edge_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
pw = Pathway.objects.get(package=p, uuid=pathway_uuid)
|
||||
e = Edge.objects.get(pathway=pw, uuid=edge_uuid)
|
||||
e.delete()
|
||||
return redirect(f"{pw.url}/edge")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Edge!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Edge with id {edge_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
#########
|
||||
# Model #
|
||||
#########
|
||||
class ModelWrapper(Schema):
|
||||
relative_reasoning: List["SimpleModel"] = Field(..., alias="relative-reasoning")
|
||||
|
||||
|
||||
class ModelSchema(Schema):
|
||||
aliases: List[str] = Field([], alias="aliases")
|
||||
description: str = Field(None, alias="description")
|
||||
evalPackages: List["SimplePackage"] = Field([])
|
||||
id: str = Field(None, alias="url")
|
||||
identifier: str = "relative-reasoning"
|
||||
# "info" : {
|
||||
# "Accuracy (Single-Gen)" : "0.5932962678936605" ,
|
||||
# "Area under PR-Curve (Single-Gen)" : "0.5654653182134282" ,
|
||||
# "Area under ROC-Curve (Single-Gen)" : "0.8178302405034772" ,
|
||||
# "Precision (Single-Gen)" : "0.6978730822873083" ,
|
||||
# "Probability Threshold" : "0.5" ,
|
||||
# "Recall/Sensitivity (Single-Gen)" : "0.4484149210261006"
|
||||
# } ,
|
||||
name: str = Field(None, alias="name")
|
||||
pathwayPackages: List["SimplePackage"] = Field([])
|
||||
reviewStatus: str = Field(None, alias="review_status")
|
||||
rulePackages: List["SimplePackage"] = Field([])
|
||||
scenarios: List["SimpleScenario"] = Field([], alias="scenarios")
|
||||
status: str
|
||||
statusMessage: str
|
||||
threshold: str
|
||||
type: str
|
||||
|
||||
|
||||
@router.get("/model", response={200: ModelWrapper, 403: Error})
|
||||
def get_models(request):
|
||||
pass
|
||||
|
||||
|
||||
@router.get("/package/{uuid:package_uuid}/model", response={200: ModelWrapper, 403: Error})
|
||||
def get_package_models(request, package_uuid, model_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
return EPModel.objects.filter(package=p)
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Getting Reaction with id {model_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
class Classify(Schema):
|
||||
smiles: str | None = None
|
||||
|
||||
|
||||
@router.get(
|
||||
"/package/{uuid:package_uuid}/model/{uuid:model_uuid}",
|
||||
response={200: ModelSchema | Any, 403: Error, 400: Error},
|
||||
)
|
||||
def get_model(request, package_uuid, model_uuid, c: Query[Classify]):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
mod = EPModel.objects.get(package=p, uuid=model_uuid)
|
||||
|
||||
if c.smiles:
|
||||
if c.smiles == "":
|
||||
return 400, {"message": "Received empty SMILES"}
|
||||
|
||||
try:
|
||||
stand_smiles = FormatConverter.standardize(c.smiles)
|
||||
except ValueError:
|
||||
return 400, {"message": f'"{c.smiles}" is not a valid SMILES'}
|
||||
|
||||
from epdb.tasks import dispatch_eager, predict_simple
|
||||
|
||||
pred_res = dispatch_eager(request.user, predict_simple, mod.pk, stand_smiles)
|
||||
|
||||
result = []
|
||||
|
||||
for pr in pred_res:
|
||||
if len(pr) > 0:
|
||||
products = []
|
||||
for prod_set in pr.product_sets:
|
||||
products.append(tuple([x for x in prod_set]))
|
||||
|
||||
res = {
|
||||
"probability": pr.probability,
|
||||
"products": list(set(products)),
|
||||
}
|
||||
|
||||
if pr.rule:
|
||||
res["id"] = pr.rule.url
|
||||
res["identifier"] = pr.rule.get_rule_identifier()
|
||||
res["name"] = pr.rule.name
|
||||
res["reviewStatus"] = (
|
||||
"reviewed" if pr.rule.package.reviewed else "unreviewed"
|
||||
)
|
||||
|
||||
result.append(res)
|
||||
|
||||
return result
|
||||
|
||||
return mod
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Getting Reaction with id {model_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
@router.delete("/package/{uuid:package_uuid}/model/{uuid:model_uuid}")
|
||||
def delete_model(request, package_uuid, model_uuid):
|
||||
try:
|
||||
p = PackageManager.get_package_by_id(request.user, package_uuid)
|
||||
|
||||
if PackageManager.writable(request.user, p):
|
||||
m = EPModel.objects.get(package=p, uuid=model_uuid)
|
||||
m.delete()
|
||||
return redirect(f"{p.url}/model")
|
||||
else:
|
||||
raise ValueError("You do not have the rights to delete this Model!")
|
||||
except ValueError:
|
||||
return 403, {
|
||||
"message": f"Deleting Model with id {model_uuid} failed due to insufficient rights!"
|
||||
}
|
||||
|
||||
|
||||
###########
|
||||
# Setting #
|
||||
###########
|
||||
|
||||
Reference in New Issue
Block a user