Files
enviPy-bayer/epdb/views.py

1357 lines
49 KiB
Python

import json
import logging
from django.conf import settings as s
from django.contrib.auth import get_user_model
from django.http import JsonResponse, HttpResponse, HttpResponseNotAllowed, HttpResponseBadRequest
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from utilities.chem import FormatConverter, IndigoUtils
from .logic import GroupManager, PackageManager, UserManager, SettingManager
from .models import Package, GroupPackagePermission, Group, CompoundStructure, Compound, Reaction, Rule, Pathway, Node, \
EPModel, EnviFormer, MLRelativeReasoning, RuleBaseRelativeReasoning, Scenario, SimpleAmbitRule, APIToken
logger = logging.getLogger(__name__)
def log_post_params(request):
for k, v in request.POST.items():
logger.debug(f"{k}\t{v}")
def get_base_context(request):
current_user = _anonymous_or_real(request)
ctx = {
'title': 'enviPath',
'meta': {
'version': '0.0.1',
'server_url': s.SERVER_URL,
'user': current_user,
'readable_packages': PackageManager.get_all_readable_packages(current_user, include_reviewed=True),
'writeable_packages': PackageManager.get_all_writeable_packages(current_user),
'available_groups': GroupManager.get_groups(current_user),
'available_settings': SettingManager.get_all_settings(current_user),
'enabled_features': [],
'debug': s.DEBUG,
},
}
return ctx
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')
def breadcrumbs(first_level_object=None, second_level_namespace=None, second_level_object=None):
bread = [
{'Home': s.SERVER_URL},
{'Package': s.SERVER_URL + '/package'},
]
if first_level_object is not None:
bread.append({first_level_object.name: first_level_object.url})
if second_level_namespace is not None:
bread.append({f'{second_level_namespace}'.capitalize(): first_level_object.url + f'/{second_level_namespace}'})
if second_level_object is not None:
bread.append({second_level_object.name: second_level_object.url})
return bread
def index(request):
current_user = _anonymous_or_real(request)
context = get_base_context(request)
context['title'] = 'enviPath - Home'
context['meta']['current_package'] = context['meta']['user'].default_package
if request.GET.get('getMLServerPath', False):
return JsonResponse({"mlServerPath": s.SERVER_URL})
return render(request, 'index/index.html', context)
def packages(request):
current_user = _anonymous_or_real(request)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Packages'
context['object_type'] = 'package'
context['meta']['current_package'] = context['meta']['user'].default_package
reviewed_package_qs = Package.objects.filter(reviewed=True)
unreviewed_package_qs = PackageManager.get_all_readable_packages(current_user)
context['reviewed_objects'] = reviewed_package_qs
context['unreviewed_objects'] = unreviewed_package_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
hidden = request.POST.get('hidden', None)
if hidden is not None:
pass
else:
package_name = request.POST.get('package-name')
package_description = request.POST.get('package-description', s.DEFAULT_VALUES['description'])
# group = GroupManager.get_group_by_url(request.user, request.POST.get('package-group'))
created_package = PackageManager.create_package(current_user, package_name, package_description)
return redirect(created_package.url)
elif request.method == 'OPTIONS':
response = HttpResponse()
response['allow'] = ','.join(['GET', 'POST'])
return response
else:
return HttpResponseNotAllowed(['GET', 'POST'])
def compounds(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Compounds'
context['object_type'] = 'compound'
context['meta']['current_package'] = context['meta']['user'].default_package
reviewed_compound_qs = Compound.objects.none()
for p in PackageManager.get_reviewed_packages():
reviewed_compound_qs |= Compound.objects.filter(package=p)
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": True}
for pw in reviewed_compound_qs
]
})
context['reviewed_objects'] = reviewed_compound_qs.order_by('name')
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
# delegate to default package
current_user = _anonymous_or_real(request)
default_package = current_user.default_package
return package_compounds(request, default_package.uuid)
def rules(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Rules'
context['object_type'] = 'rule'
context['meta']['current_package'] = context['meta']['user'].default_package
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Rule': s.SERVER_URL + '/rule'},
]
reviewed_rule_qs = Rule.objects.none()
for p in PackageManager.get_reviewed_packages():
reviewed_rule_qs |= Rule.objects.filter(package=p).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": True}
for pw in reviewed_rule_qs
]
})
context['reviewed_objects'] = reviewed_rule_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
# delegate to default package
current_user = _anonymous_or_real(request)
default_package = current_user.default_package
return package_rules(request, default_package.uuid)
def reactions(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Reactions'
context['object_type'] = 'reaction'
context['meta']['current_package'] = context['meta']['user'].default_package
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Reaction': s.SERVER_URL + '/reaction'},
]
reviewed_reaction_qs = Reaction.objects.none()
for p in PackageManager.get_reviewed_packages():
reviewed_reaction_qs |= Reaction.objects.filter(package=p).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": True}
for pw in reviewed_reaction_qs
]
})
context['reviewed_objects'] = reviewed_reaction_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
# delegate to default package
current_user = _anonymous_or_real(request)
default_package = current_user.default_package
return package_reactions(request, default_package.uuid)
def pathways(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Pathways'
context['object_type'] = 'pathway'
context['meta']['current_package'] = context['meta']['user'].default_package
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Pathway': s.SERVER_URL + '/pathway'},
]
reviewed_pathway_qs = Pathway.objects.none()
for p in PackageManager.get_reviewed_packages():
reviewed_pathway_qs |= Pathway.objects.filter(package=p).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": True}
for pw in reviewed_pathway_qs
]
})
context['reviewed_objects'] = reviewed_pathway_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
# delegate to default package
current_user = _anonymous_or_real(request)
default_package = current_user.default_package
return package_pathways(request, default_package.uuid)
def scenarios(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Scenarios'
context['object_type'] = 'scenario'
context['meta']['current_package'] = context['meta']['user'].default_package
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Scenario': s.SERVER_URL + '/scenario'},
]
reviewed_scenario_qs = Scenario.objects.none()
for p in PackageManager.get_reviewed_packages():
reviewed_scenario_qs |= Scenario.objects.filter(package=p).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": True}
for pw in reviewed_scenario_qs
]
})
context['reviewed_objects'] = reviewed_scenario_qs
return render(request, 'collections/objects_list.html', context)
# TODO
# elif request.method == 'POST':
# # delegate to default package
# default_package = request.user.default_package
# return package_scenarios(request, default_package.uuid)
def models(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Models'
context['object_type'] = 'model'
context['meta']['current_package'] = context['meta']['user'].default_package
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Model': s.SERVER_URL + '/model'},
]
context['model_types'] = {
'ML Relative Reasoning': 'ml-relative-reasoning',
'Rule Based Relative Reasoning': 'rule-based-relative-reasoning',
'EnviFormer': 'enviformer',
}
for k, v in s.CLASSIFIER_PLUGINS.items():
context['model_types'][v.display()] = k
reviewed_model_qs = EPModel.objects.none()
for p in PackageManager.get_reviewed_packages():
reviewed_model_qs |= EPModel.objects.filter(package=p).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": True}
for pw in reviewed_model_qs
]
})
context['reviewed_objects'] = reviewed_model_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
current_user = _anonymous_or_real(request)
default_package = current_user.default_package
return package_models(request, default_package.uuid)
def search(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = 'enviPath - Search'
context['object_type'] = 'model'
context['meta']['current_package'] = context['meta']['user'].default_package
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Search': s.SERVER_URL + '/search'},
]
# TODO perm
reviewed_package_qs = Package.objects.filter(reviewed=True)
unreviewed_package_qs = Package.objects.filter(reviewed=False)
context['reviewed_objects'] = reviewed_package_qs
context['unreviewed_objects'] = unreviewed_package_qs
return render(request, 'search.html', context)
def package_models(request, package_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - Models'
context['meta']['current_package'] = current_package
context['object_type'] = 'model'
context['breadcrumbs'] = breadcrumbs(current_package, 'model')
reviewed_model_qs = EPModel.objects.none()
unreviewed_model_qs = EPModel.objects.none()
if current_package.reviewed:
reviewed_model_qs = EPModel.objects.filter(package=current_package).order_by('name')
else:
unreviewed_model_qs = EPModel.objects.filter(package=current_package).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": current_package.reviewed}
for pw in (reviewed_model_qs if current_package.reviewed else unreviewed_model_qs)
]
})
context['reviewed_objects'] = reviewed_model_qs
context['unreviewed_objects'] = unreviewed_model_qs
context['model_types'] = {
'ML Relative Reasoning': 'ml-relative-reasoning',
'Rule Based Relative Reasoning': 'rule-based-relative-reasoning',
'EnviFormer': 'enviformer',
}
for k, v in s.CLASSIFIER_PLUGINS.items():
context['model_types'][v.display()] = k
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
name = request.POST.get('model-name')
description = request.POST.get('model-description')
model_type = request.POST.get('model-type')
if model_type == 'enviformer':
threshold = float(request.POST.get(f'{model_type}-threshold', 0.5))
mod = EnviFormer.create(current_package, name, description, threshold)
elif model_type == 'ml-relative-reasoning':
threshold = float(request.POST.get(f'{model_type}-threshold', 0.5))
fingerprinter = request.POST.get(f'{model_type}-fingerprinter')
rule_packages = request.POST.getlist(f'{model_type}-rule-packages')
data_packages = request.POST.getlist(f'{model_type}-data-packages')
eval_packages = request.POST.getlist(f'{model_type}-evaluation-packages', [])
# get Package objects from urls
rule_package_objs = [PackageManager.get_package_by_url(current_user, p) for p in rule_packages]
data_package_objs = [PackageManager.get_package_by_url(current_user, p) for p in data_packages]
eval_packages_objs = [PackageManager.get_package_by_url(current_user, p) for p in eval_packages]
mod = MLRelativeReasoning.create(
current_package,
name,
description,
rule_package_objs,
data_package_objs,
eval_packages_objs,
threshold
)
from .tasks import build_model
build_model.delay(mod.pk)
elif model_type == 'rule-base-relative-reasoning':
mod = RuleBaseRelativeReasoning()
mod.save()
return redirect(mod.url)
def package_model(request, package_uuid, model_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_model = EPModel.objects.get(package=current_package, uuid=model_uuid)
if request.method == 'GET':
if request.GET.get('classify', False):
smiles = request.GET['smiles']
stand_smiles = FormatConverter.standardize(smiles)
pred_res = current_model.predict(stand_smiles)
res = []
for pr in pred_res:
if len(pr) > 0:
products = []
for prod_set in pr.product_sets:
print(f"Checking {prod_set}")
products.append(tuple([x for x in prod_set]))
res.append({
'products': list(set(products)),
'probability': pr.probability,
'btrule': {k: getattr(pr.rule, k) for k in ['url', 'name']} if pr.rule is not None else None
})
return JsonResponse(res, safe=False)
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_model.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'model'
context['breadcrumbs'] = breadcrumbs(current_package, 'model', current_model)
context['model'] = current_model
return render(request, 'objects/model.html', context)
if request.method == 'POST':
if hidden := request.POST.get('hidden', None):
if hidden == 'delete-model':
current_model.delete()
return redirect(current_package.url + '/model')
else:
return HttpResponseBadRequest()
else:
return HttpResponseBadRequest()
#
# new_compound_name = request.POST.get('compound-name')
# new_compound_description = request.POST.get('compound-description')
#
# if new_compound_name:
# current_compound.name = new_compound_name
#
# if new_compound_description:
# current_compound.description = new_compound_description
#
# if any([new_compound_name, new_compound_description]):
# current_compound.save()
# return redirect(current_compound.url)
# else:
# return HttpResponseBadRequest()
def package(request, package_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'package'
context['breadcrumbs'] = breadcrumbs(current_package)
context['package'] = current_package
context['package_group'] = GroupPackagePermission.objects.filter(package=current_package,
permission=GroupPackagePermission.ALL)
return render(request, 'objects/package.html', context)
elif request.method == 'POST':
if hidden := request.POST.get('hidden', None):
if hidden == 'delete-package':
print(current_package.delete())
return redirect(s.SERVER_URL + '/package')
else:
return HttpResponseBadRequest()
new_package_name = request.POST.get('package-name')
new_package_description = request.POST.get('package-description')
if new_package_name:
current_package.name = new_package_name
if new_package_description:
current_package.description = new_package_description
if any([new_package_name, new_package_description]):
current_package.save()
return redirect(current_package.url)
else:
return HttpResponseBadRequest()
# https://envipath.org/package/<id>/compound
def package_compounds(request, package_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - Compounds'
context['meta']['current_package'] = current_package
context['object_type'] = 'compound'
context['breadcrumbs'] = breadcrumbs(current_package, 'compound')
reviewed_compound_qs = Compound.objects.none()
unreviewed_compound_qs = Compound.objects.none()
if current_package.reviewed:
reviewed_compound_qs = Compound.objects.filter(package=current_package).order_by('name')
else:
unreviewed_compound_qs = Compound.objects.filter(package=current_package).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": current_package.reviewed}
for pw in (reviewed_compound_qs if current_package.reviewed else unreviewed_compound_qs)
]
})
context['reviewed_objects'] = reviewed_compound_qs
context['unreviewed_objects'] = unreviewed_compound_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
compound_name = request.POST.get('compound-name')
compound_smiles = request.POST.get('compound-smiles')
compound_description = request.POST.get('compound-description')
c = Compound.create(current_package, compound_smiles, compound_name, compound_description)
return redirect(c.url)
# https://envipath.org/package/<id>/compound/<id>
def package_compound(request, package_uuid, compound_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_compound = Compound.objects.get(package=current_package, uuid=compound_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_compound.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'compound'
context['breadcrumbs'] = breadcrumbs(current_package, 'compound', current_compound)
context['compound'] = current_compound
return render(request, 'objects/compound.html', context)
if request.method == 'POST':
if hidden := request.POST.get('hidden', None):
if hidden == 'delete-compound':
current_compound.delete()
return redirect(current_package.url + '/compound')
else:
return HttpResponseBadRequest()
new_compound_name = request.POST.get('compound-name')
new_compound_description = request.POST.get('compound-description')
if new_compound_name:
current_compound.name = new_compound_name
if new_compound_description:
current_compound.description = new_compound_description
if any([new_compound_name, new_compound_description]):
current_compound.save()
return redirect(current_compound.url)
else:
return HttpResponseBadRequest()
# https://envipath.org/package/<uuid>/compound/<uuid>/structure
def package_compound_structures(request, package_uuid, compound_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_compound = Compound.objects.get(package=current_package, uuid=compound_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_compound.name} - Structures'
context['meta']['current_package'] = current_package
context['object_type'] = 'structure'
reviewed_compound_structure_qs = CompoundStructure.objects.none()
unreviewed_compound_structure_qs = CompoundStructure.objects.none()
if package.reviewed:
reviewed_compound_structure_qs = current_compound.structures.order_by('name')
else:
unreviewed_compound_structure_qs = current_compound.structures.order_by('name')
context['reviewed_objects'] = reviewed_compound_structure_qs
context['unreviewed_objects'] = unreviewed_compound_structure_qs
return render(request, 'collections/objects_list.html', context)
# https://envipath.org/package/<id>/compound/<id>/structure/<id>
def package_compound_structure(request, package_uuid, compound_uuid, structure_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_compound = Compound.objects.get(package=current_package, uuid=compound_uuid)
current_structure = CompoundStructure.get(compound=current_compound, uuid=structure_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_compound.name} - {current_structure.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'compound'
context['compound_structure'] = current_structure
return render(request, 'objects/compound_structure.html', context)
# https://envipath.org/package/<id>/rule
def package_rules(request, package_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - Rules'
context['meta']['current_package'] = current_package
context['object_type'] = 'rule'
context['breadcrumbs'] = breadcrumbs(current_package, 'rule')
reviewed_rule_qs = Rule.objects.none()
unreviewed_rule_qs = Rule.objects.none()
if current_package.reviewed:
reviewed_rule_qs = Rule.objects.filter(package=current_package).order_by('name')
else:
unreviewed_rule_qs = Rule.objects.filter(package=current_package).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": current_package.reviewed}
for pw in (reviewed_rule_qs if current_package.reviewed else unreviewed_rule_qs)
]
})
context['reviewed_objects'] = reviewed_rule_qs
context['unreviewed_objects'] = unreviewed_rule_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
for k, v in request.POST.items():
print(k, v)
# Generic params
rule_name = request.POST.get('rule-name')
rule_description = request.POST.get('rule-description')
rule_type = request.POST.get('rule-type')
params = {}
# Obtain parameters as required by rule type
if rule_type == 'SimpleAmbitRule':
params['smirks'] = request.POST.get('rule-smirks')
params['reactant_smarts'] = request.POST.get('rule-reactant-smarts')
params['product_smarts'] = request.POST.get('rule-product-smarts')
elif rule_type == 'SimpleRDKitRule':
params['reaction_smarts'] = request.POST.get('rule-reaction-smarts')
elif rule_type == 'ParallelRule':
pass
elif rule_type == 'SequentialRule':
pass
else:
return HttpResponseBadRequest()
r = Rule.create(current_package, rule_type, name=rule_name, description=rule_description, **params)
return redirect(r.url)
# https://envipath.org/package/<id>/rule/<id>
def package_rule(request, package_uuid, rule_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_rule = Rule.objects.get(package=current_package, uuid=rule_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_rule.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'rule'
context['breadcrumbs'] = breadcrumbs(current_package, 'rule', current_rule)
context['rule'] = current_rule
if isinstance(current_rule, SimpleAmbitRule):
return render(request, 'objects/simple_rule.html', context)
else: # isinstance(current_rule, ParallelRule) or isinstance(current_rule, SequentialRule):
return render(request, 'objects/composite_rule.html', context)
if request.method == 'POST':
if hidden := request.POST.get('hidden', None):
if hidden == 'delete-rule':
current_rule.delete()
return redirect(current_package.url + '/rule')
else:
return HttpResponseBadRequest()
# TODO update!
# https://envipath.org/package/<id>/reaction
def package_reactions(request, package_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_package.name} - Reactions'
context['meta']['current_package'] = current_package
context['object_type'] = 'reaction'
context['breadcrumbs'] = breadcrumbs(current_package, 'reaction')
reviewed_reaction_qs = Reaction.objects.none()
unreviewed_reaction_qs = Reaction.objects.none()
if current_package.reviewed:
reviewed_reaction_qs = Reaction.objects.filter(package=current_package).order_by('name')
else:
unreviewed_reaction_qs = Reaction.objects.filter(package=current_package).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": current_package.reviewed}
for pw in (reviewed_reaction_qs if current_package.reviewed else unreviewed_reaction_qs)
]
})
context['reviewed_objects'] = reviewed_reaction_qs
context['unreviewed_objects'] = unreviewed_reaction_qs
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
reaction_name = request.POST.get('reaction-name')
reaction_description = request.POST.get('reaction-description')
reactions_smirks = request.POST.get('reaction-smirks')
educts = reactions_smirks.split('>>')[0].split('.')
products = reactions_smirks.split('>>')[1].split('.')
r = Reaction.create(current_package, name=reaction_name, description=reaction_description, educts=educts,
products=products)
return redirect(r.url)
# https://envipath.org/package/<id>/reaction/<id>
def package_reaction(request, package_uuid, reaction_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_reaction = Reaction.objects.get(package=current_package, uuid=reaction_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_reaction.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'reaction'
context['breadcrumbs'] = breadcrumbs(current_package, 'reaction', current_reaction)
context['reaction'] = current_reaction
return render(request, 'objects/reaction.html', context)
if request.method == 'POST':
if hidden := request.POST.get('hidden', None):
if hidden == 'delete-reaction':
current_reaction.delete()
return redirect(current_package.url + '/reaction')
else:
return HttpResponseBadRequest()
new_reaction_name = request.POST.get('reaction-name')
new_reaction_description = request.POST.get('reaction-description')
if new_reaction_name:
current_reaction.name = new_reaction_name
if new_reaction_description:
current_reaction.description = new_reaction_description
if any([new_reaction_name, new_reaction_description]):
current_reaction.save()
return redirect(current_reaction.url)
else:
return HttpResponseBadRequest()
# https://envipath.org/package/<id>/pathway
def package_pathways(request, package_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - Pathways'
context['meta']['current_package'] = current_package
context['object_type'] = 'pathway'
context['breadcrumbs'] = breadcrumbs(current_package, 'pathway')
reviewed_pathway_qs = Pathway.objects.none()
unreviewed_pathway_qs = Pathway.objects.none()
if current_package.reviewed:
reviewed_pathway_qs = Pathway.objects.filter(package=current_package).order_by('name')
else:
unreviewed_pathway_qs = Pathway.objects.filter(package=current_package).order_by('name')
if request.GET.get('all'):
return JsonResponse({
"objects": [
{"name": pw.name, "url": pw.url, "reviewed": current_package.reviewed}
for pw in (reviewed_pathway_qs if current_package.reviewed else unreviewed_pathway_qs)
]
})
context['reviewed_objects'] = reviewed_pathway_qs
context['unreviewed_objects'] = unreviewed_pathway_qs
return render(request, 'collections/objects_list.html', context)
if request.method == 'POST':
log_post_params(request)
name = request.POST.get('name', 'Pathway ' + str(Pathway.objects.filter(package=current_package).count()))
description = request.POST.get('description', s.DEFAULT_VALUES['description'])
pw_mode = request.POST.get('predict', 'predict')
smiles = request.POST.get('smiles')
if smiles is None or smiles == '':
return HttpResponseBadRequest()
stand_smiles = FormatConverter.standardize(smiles)
pw = Pathway.create(current_package, name, description, stand_smiles)
if pw_mode != 'build':
pred_setting = current_user.prediction_settings()
from .tasks import predict
predict.delay(pw.pk, pred_setting.pk)
return redirect(pw.url)
# https://envipath.org/package/<id>/pathway/<id>
def package_pathway(request, package_uuid, pathway_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_pathway = Pathway.objects.get(package=current_package, uuid=pathway_uuid)
if request.method == 'GET':
if request.GET.get("last_modified", False):
return JsonResponse({'modified': current_pathway.modified.strftime('%Y-%m-%d %H:%M:%S')})
context = get_base_context(request)
context['title'] = f'enviPath - {current_package.name} - {current_pathway.name}'
context['meta']['current_package'] = current_package
context['object_type'] = 'pathway'
context['breadcrumbs'] = breadcrumbs(current_package, 'pathway', current_pathway)
context['pathway'] = current_pathway
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Package': s.SERVER_URL + '/package'},
{current_package.name: current_package.url},
{'Pathway': current_package.url + '/pathway'},
{current_pathway.name: current_pathway.url},
]
return render(request, 'objects/pathway.html', context)
# return render(request, 'pathway_playground2.html', context)
if request.method == 'POST':
if hidden := request.POST.get('hidden', None):
if hidden == 'delete-pathway':
current_pathway.delete()
return redirect(current_package.url + '/pathway')
else:
return HttpResponseBadRequest()
#
#
#
# def package_relative_reasonings(request, package_id):
# if request.method == 'GET':
# pass
#
#
# def package_relative_reasoning(request, package_id, relative_reasoning_id):
# current_user = _anonymous_or_real(request)
#
# if request.method == 'GET':
# pass
# elif request.method == 'POST':
# pass
#
# #
# #
# # # https://envipath.org/package/<id>/pathway/<id>/node
# # def package_pathway_nodes(request, package_id, pathway_id):
# # pass
# #
# #
# https://envipath.org/package/<id>/pathway/<id>/node/<id>
def package_pathway_node(request, package_uuid, pathway_uuid, node_uuid):
current_user = _anonymous_or_real(request)
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
current_pathway = Pathway.objects.get(package=current_package, uuid=pathway_uuid)
current_node = Node.objects.get(pathway=current_pathway, uuid=node_uuid)
if request.method == 'GET':
is_image_request = request.GET.get('image')
if is_image_request:
if is_image_request == 'svg':
svg_data = current_node.as_svg
return HttpResponse(svg_data, content_type="image/svg+xml")
# #
# #
# # # https://envipath.org/package/<id>/pathway/<id>/edge
# # def package_pathway_edges(request, package_id, pathway_id):
# # pass
# #
# #
# # # https://envipath.org/package/<id>/pathway/<id>/edge/<id>
# # def package_pathway_edge(request, package_id, pathway_id, edge_id):
# # pass
# #
# #
# # https://envipath.org/package/<id>/scenario
# def package_scenarios(request, package_id):
# current_user = _anonymous_or_real(request)
#
# if request.method == 'GET':
# context = get_base_context(request)
# current_package = PackageManager.get_package_by_id(current_user, package_id)
# context['meta']['current_package'] = current_package
# context['object_type'] = 'scenario'
#
# reviewed_scenario_qs = Scenario.objects.none()
# unreviewed_scenario_qs = Scenario.objects.none()
#
# current_package = PackageManager.get_package_by_id(current_user, package_id)
# if current_package.reviewed:
# reviewed_scenario_qs = Scenario.objects.filter(package=current_package).order_by('name')
# else:
# unreviewed_scenario_qs = Scenario.objects.filter(package=current_package).order_by('name')
#
# context['reviewed_objects'] = reviewed_scenario_qs
# context['unreviewed_objects'] = unreviewed_scenario_qs
#
# return render(request, 'collections/objects_list.html', context)
# #
# #
# # # https://envipath.org/package/<id>/scenario/<id>
# # def package_scenario(request, package_id, scenario_id):
# # pass
### END UNTESTED
##############
# User/Group #
##############
def users(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - Users'
context['meta']['current_package'] = context['meta']['user'].default_package
context['object_type'] = 'user'
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'User': s.SERVER_URL + '/user'},
]
context['objects'] = get_user_model().objects.all()
return render(request, 'collections/objects_list.html', context)
if request.method == 'POST':
is_login = bool(request.POST.get('login', False))
is_register = bool(request.POST.get('register', False))
if is_login:
from django.contrib.auth import authenticate
from django.contrib.auth import login
username = request.POST.get('username')
password = request.POST.get('password')
# Get email for username
try:
email = get_user_model().objects.get(username=username).email
except get_user_model().DoesNotExists:
return HttpResponseBadRequest()
user = authenticate(username=email, password=password)
if user is not None:
login(request, user)
return redirect(s.SERVER_URL)
else:
return HttpResponseBadRequest()
elif is_register:
username = request.POST.get('username')
email = request.POST.get('email')
password = request.POST.get('password')
rpassword = request.POST.get('rpassword')
if password != rpassword:
pass
u = UserManager.create_user(username, email, password)
return redirect(s.SERVER_URL)
def user(request, user_uuid):
current_user = _anonymous_or_real(request)
if request.method == 'GET':
# Check if current user is the one matching to the url
if str(current_user.uuid) != user_uuid and not current_user.is_superuser:
return HttpResponseBadRequest()
context = get_base_context(request)
context['title'] = f'enviPath - User'
context['object_type'] = 'user'
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'User': s.SERVER_URL + '/user'},
{current_user.username: current_user.url}
]
context['user'] = current_user
model_qs = EPModel.objects.none()
for p in PackageManager.get_all_readable_packages(current_user, include_reviewed=True):
model_qs |= p.models
context['models'] = model_qs
context['tokens'] = APIToken.objects.filter(user=current_user)
return render(request, 'objects/user.html', context)
elif request.method == 'POST':
is_hidden_method = bool(request.POST.get('hidden', False))
if is_hidden_method and request.POST['hidden'] == 'request-api-token':
name = request.POST.get('name', 'No Name')
valid_for = min(max(int(request.POST.get('valid-for', 90)), 1), 90)
token, raw_token = APIToken.create_token(request.user, name=name, valid_for=valid_for)
return JsonResponse({"raw_token": raw_token, 'token': {'id': token.id, 'name': token.name}})
if is_hidden_method and request.POST['hidden'] == 'delete':
token_id = request.POST.get('token-id')
if token_id is None:
return HttpResponseBadRequest("Token ID missing!")
try:
APIToken.objects.get(user=current_user, id=token_id).delete()
except APIToken.DoesNotExist:
return HttpResponseBadRequest("User and Token ID combination invalid!")
return HttpResponse("success")
is_logout = bool(request.POST.get('logout', False))
if is_logout:
from django.contrib.auth import logout
logout(request)
return redirect(s.SERVER_URL)
prediction_model_pk = request.POST.get('model')
prediction_threshold = request.POST.get('threshold')
prediction_max_nodes = request.POST.get('max_nodes')
prediction_max_depth = request.POST.get('max_depth')
if all([prediction_model_pk, prediction_threshold, prediction_max_nodes, prediction_max_depth]):
# validate input..
mod = EPModel.objects.get(id=prediction_model_pk)
if not PackageManager.readable(current_user, mod.package):
return HttpResponseBadRequest()
threshold = float(prediction_threshold)
if threshold < 0 or threshold > 1:
return HttpResponseBadRequest()
max_nodes = min(max(int(prediction_max_nodes), 1), 50)
max_depth = min(max(int(prediction_max_depth), 1), 8)
setting = {
'model': mod,
'model_parameters': {
'threshold': threshold
},
'truncator': {
'max_nodes': max_nodes,
'max_depth': max_depth,
}
}
print(setting)
return HttpResponseBadRequest()
def groups(request):
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - Groups'
context['meta']['current_package'] = context['meta']['user'].default_package
context['object_type'] = 'group'
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Group': s.SERVER_URL + '/group'},
]
context['objects'] = Group.objects.all()
return render(request, 'collections/objects_list.html', context)
elif request.method == 'POST':
group_name = request.POST.get('group-name')
group_description = request.POST.get('group-description', s.DEFAULT_VALUES['description'])
g = Group()
g.name = group_name
g.description = group_description
g.save()
g.user_member.add(request.user)
g.save()
return redirect(g.url)
def group(request, group_uuid):
current_user = _anonymous_or_real(request)
current_group = GroupManager.get_group_by_id(current_user, group_uuid)
if request.method == 'GET':
context = get_base_context(request)
context['title'] = f'enviPath - {current_group.name}'
context['object_type'] = 'group'
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Group': s.SERVER_URL + '/group'},
{current_group.name: current_group.url}
]
context['group'] = current_group
return render(request, 'objects/group.html', context)
def settings(request):
current_user = _anonymous_or_real(request)
context = get_base_context(request)
if request.method == 'GET':
context['object_type'] = 'setting'
# Even if settings are aready in "meta", for consistency add it on root level
context['settings'] = SettingManager.get_all_settings(current_user)
context['breadcrumbs'] = [
{'Home': s.SERVER_URL},
{'Group': s.SERVER_URL + '/setting'},
]
return
elif request.method == 'POST':
if s.DEBUG:
for k, v in request.POST.items():
logger.info("Parameters received:")
logger.info(f"{k}\t{v}")
name = request.POST.get('prediction-setting-name')
description = request.POST.get('prediction-setting-description')
new_default = request.POST.get('prediction-setting-new-default', 'off') == 'on'
max_nodes = min(max(int(request.POST.get('prediction-setting-max-nodes', 1)), s.DEFAULT_MAX_NUMBER_OF_NODES), s.DEFAULT_MAX_NUMBER_OF_NODES)
max_depth = min(max(int(request.POST.get('prediction-setting-max-depth', 1)), s.DEFAULT_MAX_DEPTH), s.DEFAULT_MAX_DEPTH)
tp_gen_method = request.POST.get('tp-generation-method')
params = {}
if tp_gen_method == 'model-based-prediction-setting':
model_url = request.POST.get('model-based-prediction-setting-model')
model_uuid = model_url.split('/')[-1]
params['model'] = EPModel.objects.get(uuid=model_uuid)
params['model_threshold'] = request.POST.get('model-based-prediction-setting-threshold',
s.DEFAULT_MODEL_THRESHOLD)
if not PackageManager.readable(current_user, params['model'].package):
raise ValueError("")
elif tp_gen_method == 'rule-based-prediction-setting':
rule_packages = request.POST.getlist('rule-based-prediction-setting-packages')
params['rule_packages'] = [PackageManager.get_package_by_url(current_user, p) for p in rule_packages]
else:
raise ValueError("")
created_setting = SettingManager.create_setting(current_user, name=name, description=description,
max_nodes=max_nodes, max_depth=max_depth, **params)
if new_default:
current_user.default_setting = created_setting
current_user.save()
return HttpResponse("Success!")
def setting(request, setting_uuid):
pass
###########
# KETCHER #
###########
def indigo(request):
from indigo import Indigo
return JsonResponse({'Indigo': {'version': Indigo().version()}})
@csrf_exempt
def aromatize(request):
if request.method == 'POST':
data = json.loads(request.body)
mol_data = data.get('struct')
aromatized = IndigoUtils.aromatize(mol_data, False)
return JsonResponse({"struct": aromatized})
else:
return HttpResponseBadRequest()
@csrf_exempt
def dearomatize(request):
if request.method == 'POST':
data = json.loads(request.body)
mol_data = data.get('struct')
dearomatized = IndigoUtils.dearomatize(mol_data, False)
return JsonResponse({"struct": dearomatized})
else:
return HttpResponseBadRequest()
@csrf_exempt
def layout(request):
if request.method == 'POST':
data = json.loads(request.body)
mol_data = data.get('struct')
lay = IndigoUtils.layout(mol_data)
return JsonResponse({"struct": lay})
else:
return HttpResponseBadRequest()
##########################
# Generic/Non-Persistent #
##########################
def depict(request):
if smiles := request.GET.get('smiles'):
return HttpResponse(IndigoUtils.mol_to_svg(smiles), content_type='image/svg+xml')