Compare commits
85 Commits
main
...
beta_2025-
| Author | SHA1 | Date | |
|---|---|---|---|
| d5ebb23622 | |||
| 93dd811e39 | |||
| 9a4735246f | |||
| 1f863fdcd6 | |||
| 1effaeb342 | |||
| 386098b8a6 | |||
| ef697ac5f5 | |||
| 68a3f3b982 | |||
| afeb56622c | |||
| 22f0bbe10b | |||
| 36879c266b | |||
| c2c46fbfa7 | |||
| d2f4fdc58a | |||
| 3f2b046bd6 | |||
| 7ad4112343 | |||
| 3f5bb76633 | |||
| b757a07f91 | |||
| b5c759d74e | |||
| b3079834c1 | |||
| f03ade0e94 | |||
| 50db2fb372 | |||
| 762a6b7baf | |||
| ce349a287b | |||
| 7905a8c2c1 | |||
| af3981d96e | |||
| 62e6448448 | |||
| 31783306e2 | |||
| e82fe7e87e | |||
| 4463bf1bc8 | |||
| abfd683640 | |||
| 3453a169e1 | |||
| 5477b5b3d4 | |||
| 1a6608287d | |||
| a16035677c | |||
| 498a53ab3d | |||
| aa3b53e94b | |||
| 3c8f0e80cb | |||
| 4158bd36cb | |||
| 4e02910c62 | |||
| 2babe7f7e2 | |||
| 7da3880a9b | |||
| 52931526c1 | |||
| dd7b28046c | |||
| 8592cfae50 | |||
| ec2b941a85 | |||
| 02d84a9b29 | |||
| 00d9188c0c | |||
| 13816ecaf3 | |||
| 6a4c8d96c3 | |||
| 97d0527565 | |||
| b45c99f7d3 | |||
| b95ec98a2f | |||
| c79a1f2040 | |||
| 6e6b394289 | |||
| ec387cc12e | |||
| a7637d046a | |||
| fc8192fb0d | |||
| c3c1d4f5cf | |||
| 3308d47071 | |||
| 1267ca8ace | |||
| ec52b8872d | |||
| 579cd519d0 | |||
| 280ddc7205 | |||
| c9d6d8b024 | |||
| a1aebfa54d | |||
| 79b4b1586c | |||
| aec61151ce | |||
| 026189ccd9 | |||
| 2c9f9038f3 | |||
| 2b8b6f286d | |||
| 2c4c9d95d9 | |||
| 43c95e3da7 | |||
| df896878f1 | |||
| 49e02ed97d | |||
| 4fff78541b | |||
| 9323a9f7d7 | |||
| 4e58a1fad7 | |||
| 9950112311 | |||
| 6eb1d1bd65 | |||
| bcd9451450 | |||
| 844d0708c9 | |||
| 7c3bc69b38 | |||
| 843e8e6f07 | |||
| acdb62c08f | |||
| ded50edaa2 |
22
.env.local.example
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Django settings
|
||||||
|
SECRET_KEY='a-secure-secret-key-for-development'
|
||||||
|
DEBUG=True
|
||||||
|
ALLOWED_HOSTS=*
|
||||||
|
|
||||||
|
# Database settings (using PostgreSQL for local development)
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=postgres
|
||||||
|
POSTGRES_DB=envipath
|
||||||
|
POSTGRES_SERVICE_NAME=localhost
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
# Celery settings
|
||||||
|
CELERY_BROKER_URL='redis://localhost:6379/0'
|
||||||
|
CELERY_RESULT_BACKEND='redis://localhost:6379/0'
|
||||||
|
FLAG_CELERY_PRESENT=False
|
||||||
|
|
||||||
|
# Other settings
|
||||||
|
LOG_LEVEL='INFO'
|
||||||
|
SERVER_URL='http://localhost:8000'
|
||||||
|
PLUGINS_ENABLED=True
|
||||||
|
EP_DATA_DIR='data'
|
||||||
18
.env.prod.example
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# settings.py
|
||||||
|
EP_DATA_DIR=
|
||||||
|
ALLOWED_HOSTS=
|
||||||
|
DEBUG=
|
||||||
|
LOG_LEVEL=
|
||||||
|
ENVIFORMER_PRESENT=
|
||||||
|
FLAG_CELERY_PRESENT=
|
||||||
|
SERVER_URL=
|
||||||
|
PLUGINS_ENABLED=
|
||||||
|
# DB
|
||||||
|
POSTGRES_SERVICE_NAME=
|
||||||
|
POSTGRES_DB=
|
||||||
|
POSTGRES_USER=
|
||||||
|
POSTGRES_PASSWORD=
|
||||||
|
POSTGRES_PORT=
|
||||||
|
# MAIL
|
||||||
|
EMAIL_HOST_USER=
|
||||||
|
EMAIL_HOST_PASSWORD=
|
||||||
180
.gitignore
vendored
@ -1,176 +1,12 @@
|
|||||||
# ---> Python
|
*.pyc
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py,cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
cover/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
db.sqlite3-journal
|
.idea/
|
||||||
|
static/admin/
|
||||||
# Flask stuff:
|
static/django_extensions/
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
.pybuilder/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
|
||||||
# .python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# UV
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
#uv.lock
|
|
||||||
|
|
||||||
# poetry
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
||||||
#poetry.lock
|
|
||||||
|
|
||||||
# pdm
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
||||||
#pdm.lock
|
|
||||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
||||||
# in version control.
|
|
||||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
||||||
.pdm.toml
|
|
||||||
.pdm-python
|
|
||||||
.pdm-build/
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
.env
|
||||||
.venv
|
debug.log
|
||||||
env/
|
scratches/
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
data/
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
|
|
||||||
# pytype static type analyzer
|
|
||||||
.pytype/
|
|
||||||
|
|
||||||
# Cython debug symbols
|
|
||||||
cython_debug/
|
|
||||||
|
|
||||||
# PyCharm
|
|
||||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
||||||
#.idea/
|
|
||||||
|
|
||||||
# Ruff stuff:
|
|
||||||
.ruff_cache/
|
|
||||||
|
|
||||||
# PyPI configuration file
|
|
||||||
.pypirc
|
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|||||||
30
.pre-commit-config.yaml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v3.2.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-added-large-files
|
||||||
|
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.13.3
|
||||||
|
hooks:
|
||||||
|
# Run the linter.
|
||||||
|
- id: ruff-check
|
||||||
|
types_or: [python, pyi]
|
||||||
|
args: [--fix]
|
||||||
|
# Run the formatter.
|
||||||
|
- id: ruff-format
|
||||||
|
types_or: [python, pyi]
|
||||||
|
|
||||||
|
# - repo: local
|
||||||
|
# hooks:
|
||||||
|
# - id: django-check
|
||||||
|
# name: Run Django Check
|
||||||
|
# entry: uv run python manage.py check
|
||||||
|
# language: system
|
||||||
|
# pass_filenames: false
|
||||||
|
# types: [python]
|
||||||
1
.python-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.12
|
||||||
89
README.md
@ -1,2 +1,91 @@
|
|||||||
# enviPy
|
# enviPy
|
||||||
|
|
||||||
|
## Local Development Setup
|
||||||
|
|
||||||
|
These instructions will guide you through setting up the project for local development.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Python 3.11 or later
|
||||||
|
- [uv](https://github.com/astral-sh/uv) - A fast Python package installer and resolver.
|
||||||
|
- **Docker and Docker Compose** - Required for running the PostgreSQL database.
|
||||||
|
- Git
|
||||||
|
|
||||||
|
> **Note:** This application requires PostgreSQL, which uses `ArrayField`. Docker is the recommended way to run PostgreSQL locally.
|
||||||
|
|
||||||
|
### 1. Install Dependencies
|
||||||
|
|
||||||
|
This project uses `uv` to manage dependencies and `poe-the-poet` for task running. First, [install `uv` if you don't have it yet](https://docs.astral.sh/uv/guides/install-python/).
|
||||||
|
|
||||||
|
Then, sync the project dependencies. This will create a virtual environment in `.venv` and install all necessary packages, including `poe-the-poet`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv sync --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note on RDkit:** If you have a different version of rdkit installed globally, the dependency installation may fail. If this happens, please uninstall the global version and run `uv sync` again.
|
||||||
|
|
||||||
|
### 2. Set Up Environment File
|
||||||
|
|
||||||
|
Copy the example environment file for local setup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.local.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
This file contains the necessary environment variables for local development.
|
||||||
|
|
||||||
|
### 3. Quick Setup with Poe
|
||||||
|
|
||||||
|
The easiest way to set up the development environment is by using the `poe` task runner, which is executed via `uv run`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run poe setup
|
||||||
|
```
|
||||||
|
|
||||||
|
This single command will:
|
||||||
|
1. Start the PostgreSQL database using Docker Compose.
|
||||||
|
2. Run database migrations.
|
||||||
|
3. Bootstrap initial data (anonymous user, default packages, models).
|
||||||
|
|
||||||
|
After setup, start the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run poe dev
|
||||||
|
```
|
||||||
|
|
||||||
|
The application will be available at `http://localhost:8000`.
|
||||||
|
|
||||||
|
#### Other useful Poe commands:
|
||||||
|
|
||||||
|
You can list all available commands by running `uv run poe --help`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run poe db-up # Start PostgreSQL only
|
||||||
|
uv run poe db-down # Stop PostgreSQL
|
||||||
|
uv run poe migrate # Run migrations only
|
||||||
|
uv run poe bootstrap # Bootstrap data only
|
||||||
|
uv run poe shell # Open the Django shell
|
||||||
|
uv run poe clean # Remove database volumes (WARNING: destroys all data)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
* **Docker Connection Error:** If you see an error like `open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified` (on Windows), it likely means your Docker Desktop application is not running. Please start Docker Desktop and try the command again.
|
||||||
|
|
||||||
|
* **SSH Keys for Git Dependencies:** Some dependencies are installed from private git repositories and require SSH authentication. Ensure your SSH keys are configured correctly for Git.
|
||||||
|
* For a general guide, see [GitHub's official documentation](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
|
||||||
|
* **Windows Users:** If `uv sync` hangs while fetching git dependencies, you may need to explicitly configure Git to use the Windows OpenSSH client and use the `ssh-agent` to manage your key's passphrase.
|
||||||
|
|
||||||
|
1. **Point Git to the correct SSH executable:**
|
||||||
|
```powershell
|
||||||
|
git config --global core.sshCommand "C:/Windows/System32/OpenSSH/ssh.exe"
|
||||||
|
```
|
||||||
|
2. **Enable and use the SSH agent:**
|
||||||
|
```powershell
|
||||||
|
# Run these commands in an administrator PowerShell
|
||||||
|
Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service
|
||||||
|
|
||||||
|
# Add your key to the agent. It will prompt for the passphrase once.
|
||||||
|
ssh-add
|
||||||
|
```
|
||||||
|
|||||||
20
docker-compose.dev.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:15
|
||||||
|
container_name: envipath-postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: envipath
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
5
envipath/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# This will make sure the app is always imported when
|
||||||
|
# Django starts so that shared_task will use this app.
|
||||||
|
from .celery import app as celery_app
|
||||||
|
|
||||||
|
__all__ = ("celery_app",)
|
||||||
12
envipath/api.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from epdb.api import router as epdb_app_router
|
||||||
|
from epdb.legacy_api import router as epdb_legacy_app_router
|
||||||
|
from ninja import NinjaAPI
|
||||||
|
|
||||||
|
api = NinjaAPI()
|
||||||
|
|
||||||
|
api_v1 = NinjaAPI(title="API V1 Docs", urls_namespace="api-v1")
|
||||||
|
api_legacy = NinjaAPI(title="Legacy API Docs", urls_namespace="api-legacy")
|
||||||
|
|
||||||
|
# Add routers
|
||||||
|
api_v1.add_router("/", epdb_app_router)
|
||||||
|
api_legacy.add_router("/", epdb_legacy_app_router)
|
||||||
16
envipath/asgi.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for envipath project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "envipath.settings")
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
27
envipath/celery.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
from celery.signals import setup_logging
|
||||||
|
|
||||||
|
# Set the default Django settings module for the 'celery' program.
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "envipath.settings")
|
||||||
|
|
||||||
|
app = Celery("envipath")
|
||||||
|
|
||||||
|
# Using a string here means the worker doesn't have to serialize
|
||||||
|
# the configuration object to child processes.
|
||||||
|
# - namespace='CELERY' means all celery-related configuration keys
|
||||||
|
# should have a `CELERY_` prefix.
|
||||||
|
app.config_from_object("django.conf:settings", namespace="CELERY")
|
||||||
|
|
||||||
|
|
||||||
|
@setup_logging.connect
|
||||||
|
def config_loggers(*args, **kwargs):
|
||||||
|
from logging.config import dictConfig
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
dictConfig(settings.LOGGING)
|
||||||
|
|
||||||
|
|
||||||
|
# Load task modules from all registered Django apps.
|
||||||
|
app.autodiscover_tasks()
|
||||||
359
envipath/settings.py
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
"""
|
||||||
|
Django settings for envipath project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 4.2.17.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from envipy_plugins import Classifier, Property, Descriptor
|
||||||
|
from sklearn.ensemble import RandomForestClassifier
|
||||||
|
from sklearn.tree import DecisionTreeClassifier
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
load_dotenv(BASE_DIR / ".env", override=False)
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = os.environ.get("SECRET_KEY", "secret-key")
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = os.environ.get("DEBUG", "False") == "True"
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = os.environ["ALLOWED_HOSTS"].split(",")
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
"django.contrib.admin",
|
||||||
|
"django.contrib.auth",
|
||||||
|
"django.contrib.contenttypes",
|
||||||
|
"django.contrib.sessions",
|
||||||
|
"django.contrib.messages",
|
||||||
|
"django.contrib.staticfiles",
|
||||||
|
# 3rd party
|
||||||
|
"django_extensions",
|
||||||
|
"oauth2_provider",
|
||||||
|
# Custom
|
||||||
|
"epdb",
|
||||||
|
"migration",
|
||||||
|
]
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
"django.middleware.security.SecurityMiddleware",
|
||||||
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
|
"django.middleware.common.CommonMiddleware",
|
||||||
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||||
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
|
"oauth2_provider.middleware.OAuth2TokenMiddleware",
|
||||||
|
]
|
||||||
|
|
||||||
|
OAUTH2_PROVIDER = {
|
||||||
|
"PKCE_REQUIRED": False, # Accept PKCE requests but dont require them
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.environ.get("REGISTRATION_MANDATORY", False) == "True":
|
||||||
|
MIDDLEWARE.append("epdb.middleware.login_required_middleware.LoginRequiredMiddleware")
|
||||||
|
|
||||||
|
ROOT_URLCONF = "envipath.urls"
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
|
"DIRS": (os.path.join(BASE_DIR, "templates"),),
|
||||||
|
"APP_DIRS": True,
|
||||||
|
"OPTIONS": {
|
||||||
|
"context_processors": [
|
||||||
|
"django.template.context_processors.debug",
|
||||||
|
"django.template.context_processors.request",
|
||||||
|
"django.contrib.auth.context_processors.auth",
|
||||||
|
"django.contrib.messages.context_processors.messages",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = "envipath.wsgi.application"
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django.db.backends.postgresql",
|
||||||
|
"USER": os.environ["POSTGRES_USER"],
|
||||||
|
"NAME": os.environ["POSTGRES_DB"],
|
||||||
|
"PASSWORD": os.environ["POSTGRES_PASSWORD"],
|
||||||
|
"HOST": os.environ["POSTGRES_SERVICE_NAME"],
|
||||||
|
"PORT": os.environ["POSTGRES_PORT"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
|
||||||
|
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = "en-us"
|
||||||
|
|
||||||
|
TIME_ZONE = "UTC"
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||||
|
|
||||||
|
EMAIL_SUBJECT_PREFIX = "[enviPath] "
|
||||||
|
if DEBUG:
|
||||||
|
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||||
|
else:
|
||||||
|
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
|
||||||
|
EMAIL_USE_TLS = True
|
||||||
|
EMAIL_HOST = "mail.gandi.net"
|
||||||
|
EMAIL_HOST_USER = os.environ["EMAIL_HOST_USER"]
|
||||||
|
EMAIL_HOST_PASSWORD = os.environ["EMAIL_HOST_PASSWORD"]
|
||||||
|
EMAIL_PORT = 587
|
||||||
|
DEFAULT_FROM_EMAIL = os.environ["DEFAULT_FROM_EMAIL"]
|
||||||
|
SERVER_EMAIL = os.environ["SERVER_EMAIL"]
|
||||||
|
|
||||||
|
AUTH_USER_MODEL = "epdb.User"
|
||||||
|
ADMIN_APPROVAL_REQUIRED = os.environ.get("ADMIN_APPROVAL_REQUIRED", "False") == "True"
|
||||||
|
|
||||||
|
# # SESAME
|
||||||
|
# SESAME_MAX_AGE = 300
|
||||||
|
# # TODO set to "home"
|
||||||
|
# LOGIN_REDIRECT_URL = "/"
|
||||||
|
LOGIN_URL = "/login/"
|
||||||
|
|
||||||
|
SERVER_URL = os.environ.get("SERVER_URL", "http://localhost:8000")
|
||||||
|
|
||||||
|
CSRF_TRUSTED_ORIGINS = [SERVER_URL]
|
||||||
|
|
||||||
|
AMBIT_URL = "http://localhost:9001"
|
||||||
|
DEFAULT_VALUES = {"description": "no description"}
|
||||||
|
|
||||||
|
EP_DATA_DIR = os.environ["EP_DATA_DIR"]
|
||||||
|
if not os.path.exists(EP_DATA_DIR):
|
||||||
|
os.mkdir(EP_DATA_DIR)
|
||||||
|
|
||||||
|
MODEL_DIR = os.path.join(EP_DATA_DIR, "models")
|
||||||
|
if not os.path.exists(MODEL_DIR):
|
||||||
|
os.mkdir(MODEL_DIR)
|
||||||
|
|
||||||
|
STATIC_DIR = os.path.join(EP_DATA_DIR, "static")
|
||||||
|
if not os.path.exists(STATIC_DIR):
|
||||||
|
os.mkdir(STATIC_DIR)
|
||||||
|
|
||||||
|
LOG_DIR = os.path.join(EP_DATA_DIR, "log")
|
||||||
|
if not os.path.exists(LOG_DIR):
|
||||||
|
os.mkdir(LOG_DIR)
|
||||||
|
|
||||||
|
PLUGIN_DIR = os.path.join(EP_DATA_DIR, "plugins")
|
||||||
|
if not os.path.exists(PLUGIN_DIR):
|
||||||
|
os.mkdir(PLUGIN_DIR)
|
||||||
|
|
||||||
|
# Set this as our static root dir
|
||||||
|
STATIC_ROOT = STATIC_DIR
|
||||||
|
|
||||||
|
STATIC_URL = "/static/"
|
||||||
|
|
||||||
|
# Where the sources are stored...
|
||||||
|
STATICFILES_DIRS = (BASE_DIR / "static",)
|
||||||
|
|
||||||
|
FIXTURE_DIRS = (BASE_DIR / "fixtures",)
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOGGING = {
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": True,
|
||||||
|
"formatters": {
|
||||||
|
"simple": {
|
||||||
|
"format": "[%(asctime)s] %(levelname)s %(module)s - %(message)s",
|
||||||
|
"datefmt": "%Y-%m-%d %H:%M:%S",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"handlers": {
|
||||||
|
"console": {
|
||||||
|
"level": "INFO",
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"formatter": "simple",
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"level": "DEBUG", # Or higher
|
||||||
|
"class": "logging.FileHandler",
|
||||||
|
"filename": os.path.join(LOG_DIR, "debug.log"),
|
||||||
|
"formatter": "simple",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"loggers": {
|
||||||
|
# For everything under epdb/ loaded via getlogger(__name__)
|
||||||
|
"epdb": {
|
||||||
|
"handlers": ["file"], # "console",
|
||||||
|
"propagate": True,
|
||||||
|
"level": os.environ.get("LOG_LEVEL", "INFO"),
|
||||||
|
},
|
||||||
|
# For everything under envipath/ loaded via getlogger(__name__)
|
||||||
|
"envipath": {
|
||||||
|
"handlers": ["file", "console"],
|
||||||
|
"propagate": True,
|
||||||
|
"level": os.environ.get("LOG_LEVEL", "INFO"),
|
||||||
|
},
|
||||||
|
# For everything under utilities/ loaded via getlogger(__name__)
|
||||||
|
"utilities": {
|
||||||
|
"handlers": ["file", "console"],
|
||||||
|
"propagate": True,
|
||||||
|
"level": os.environ.get("LOG_LEVEL", "INFO"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Flags
|
||||||
|
ENVIFORMER_PRESENT = os.environ.get("ENVIFORMER_PRESENT", "False") == "True"
|
||||||
|
ENVIFORMER_DEVICE = os.environ.get("ENVIFORMER_DEVICE", "cpu")
|
||||||
|
|
||||||
|
# If celery is not present set always eager to true which will cause delayed tasks to block until finished
|
||||||
|
FLAG_CELERY_PRESENT = os.environ.get("FLAG_CELERY_PRESENT", "False") == "True"
|
||||||
|
if not FLAG_CELERY_PRESENT:
|
||||||
|
CELERY_TASK_ALWAYS_EAGER = True
|
||||||
|
|
||||||
|
# Celery Configuration Options
|
||||||
|
CELERY_TIMEZONE = "Europe/Berlin"
|
||||||
|
# Celery Configuration
|
||||||
|
CELERY_BROKER_URL = "redis://localhost:6379/0" # Use Redis as message broker
|
||||||
|
CELERY_RESULT_BACKEND = "redis://localhost:6379/1"
|
||||||
|
CELERY_ACCEPT_CONTENT = ["json"]
|
||||||
|
CELERY_TASK_SERIALIZER = "json"
|
||||||
|
|
||||||
|
MODEL_BUILDING_ENABLED = os.environ.get("MODEL_BUILDING_ENABLED", "False") == "True"
|
||||||
|
APPLICABILITY_DOMAIN_ENABLED = os.environ.get("APPLICABILITY_DOMAIN_ENABLED", "False") == "True"
|
||||||
|
DEFAULT_RF_MODEL_PARAMS = {
|
||||||
|
"base_clf": RandomForestClassifier(
|
||||||
|
n_estimators=100,
|
||||||
|
max_features="log2",
|
||||||
|
random_state=42,
|
||||||
|
criterion="entropy",
|
||||||
|
ccp_alpha=0.0,
|
||||||
|
max_depth=3,
|
||||||
|
min_samples_leaf=1,
|
||||||
|
),
|
||||||
|
"num_chains": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_MODEL_PARAMS = {
|
||||||
|
"base_clf": DecisionTreeClassifier(
|
||||||
|
criterion="entropy",
|
||||||
|
max_depth=3,
|
||||||
|
min_samples_split=5,
|
||||||
|
# min_samples_leaf=5,
|
||||||
|
max_features="sqrt",
|
||||||
|
# class_weight='balanced',
|
||||||
|
random_state=42,
|
||||||
|
),
|
||||||
|
"num_chains": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_MAX_NUMBER_OF_NODES = 30
|
||||||
|
DEFAULT_MAX_DEPTH = 5
|
||||||
|
DEFAULT_MODEL_THRESHOLD = 0.25
|
||||||
|
|
||||||
|
# Loading Plugins
|
||||||
|
PLUGINS_ENABLED = os.environ.get("PLUGINS_ENABLED", "False") == "True"
|
||||||
|
if PLUGINS_ENABLED:
|
||||||
|
from utilities.plugin import discover_plugins
|
||||||
|
|
||||||
|
CLASSIFIER_PLUGINS = discover_plugins(_cls=Classifier)
|
||||||
|
PROPERTY_PLUGINS = discover_plugins(_cls=Property)
|
||||||
|
DESCRIPTOR_PLUGINS = discover_plugins(_cls=Descriptor)
|
||||||
|
else:
|
||||||
|
CLASSIFIER_PLUGINS = {}
|
||||||
|
PROPERTY_PLUGINS = {}
|
||||||
|
DESCRIPTOR_PLUGINS = {}
|
||||||
|
|
||||||
|
SENTRY_ENABLED = os.environ.get("SENTRY_ENABLED", "False") == "True"
|
||||||
|
if SENTRY_ENABLED:
|
||||||
|
import sentry_sdk
|
||||||
|
|
||||||
|
def before_send(event, hint):
|
||||||
|
# Check if was a handled exception by one of our loggers
|
||||||
|
if event.get("logger"):
|
||||||
|
for log_path in LOGGING.get("loggers").keys():
|
||||||
|
if event["logger"].startswith(log_path):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return event
|
||||||
|
|
||||||
|
sentry_sdk.init(
|
||||||
|
dsn=os.environ.get("SENTRY_DSN"),
|
||||||
|
# Add data like request headers and IP for users,
|
||||||
|
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
|
||||||
|
send_default_pii=True,
|
||||||
|
environment=os.environ.get("SENTRY_ENVIRONMENT", "development"),
|
||||||
|
before_send=before_send,
|
||||||
|
)
|
||||||
|
|
||||||
|
# compile into digestible flags
|
||||||
|
FLAGS = {
|
||||||
|
"MODEL_BUILDING": MODEL_BUILDING_ENABLED,
|
||||||
|
"CELERY": FLAG_CELERY_PRESENT,
|
||||||
|
"PLUGINS": PLUGINS_ENABLED,
|
||||||
|
"SENTRY": SENTRY_ENABLED,
|
||||||
|
"ENVIFORMER": ENVIFORMER_PRESENT,
|
||||||
|
"APPLICABILITY_DOMAIN": APPLICABILITY_DOMAIN_ENABLED,
|
||||||
|
}
|
||||||
|
|
||||||
|
# path of the URL are checked via "startswith"
|
||||||
|
# -> /password_reset/done is covered as well
|
||||||
|
LOGIN_EXEMPT_URLS = [
|
||||||
|
"/register",
|
||||||
|
"/api/legacy/",
|
||||||
|
"/o/token/",
|
||||||
|
"/o/userinfo/",
|
||||||
|
"/password_reset/",
|
||||||
|
"/reset/",
|
||||||
|
"/microsoft/",
|
||||||
|
]
|
||||||
|
|
||||||
|
# MS AD/Entra
|
||||||
|
MS_ENTRA_ENABLED = os.environ.get("MS_ENTRA_ENABLED", "False") == "True"
|
||||||
|
if MS_ENTRA_ENABLED:
|
||||||
|
# Add app to installed apps
|
||||||
|
INSTALLED_APPS.append("epauth")
|
||||||
|
# Set vars required by app
|
||||||
|
MS_ENTRA_CLIENT_ID = os.environ["MS_CLIENT_ID"]
|
||||||
|
MS_ENTRA_CLIENT_SECRET = os.environ["MS_CLIENT_SECRET"]
|
||||||
|
MS_ENTRA_TENANT_ID = os.environ["MS_TENANT_ID"]
|
||||||
|
MS_ENTRA_AUTHORITY = f"https://login.microsoftonline.com/{MS_ENTRA_TENANT_ID}"
|
||||||
|
MS_ENTRA_REDIRECT_URI = os.environ["MS_REDIRECT_URI"]
|
||||||
|
MS_ENTRA_SCOPES = os.environ.get("MS_SCOPES", "").split(",")
|
||||||
34
envipath/urls.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
"""
|
||||||
|
URL configuration for envipath project.
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/4.2/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.conf import settings as s
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import include, path
|
||||||
|
|
||||||
|
from .api import api_v1, api_legacy
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", include("epdb.urls")),
|
||||||
|
path("", include("migration.urls")),
|
||||||
|
path("admin/", admin.site.urls),
|
||||||
|
path("api/v1/", api_v1.urls),
|
||||||
|
path("api/legacy/", api_legacy.urls),
|
||||||
|
path("o/", include("oauth2_provider.urls", namespace="oauth2_provider")),
|
||||||
|
]
|
||||||
|
|
||||||
|
if s.MS_ENTRA_ENABLED:
|
||||||
|
urlpatterns.append(path("", include("epauth.urls")))
|
||||||
16
envipath/wsgi.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for envipath project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "envipath.settings")
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
0
epauth/__init__.py
Normal file
3
epauth/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
epauth/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class EpauthConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'epauth'
|
||||||
0
epauth/migrations/__init__.py
Normal file
3
epauth/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
3
epauth/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
8
epauth/urls.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("microsoft/login/", views.microsoft_login, name="microsoft_login"),
|
||||||
|
path("microsoft/callback/", views.microsoft_callback, name="microsoft_callback"),
|
||||||
|
]
|
||||||
66
epauth/views.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import msal
|
||||||
|
from django.conf import settings as s
|
||||||
|
from django.contrib.auth import login
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
from epdb.logic import UserManager
|
||||||
|
|
||||||
|
|
||||||
|
def microsoft_login(request):
|
||||||
|
msal_app = msal.ConfidentialClientApplication(
|
||||||
|
client_id=s.MS_ENTRA_CLIENT_ID,
|
||||||
|
client_credential=s.MS_ENTRA_CLIENT_SECRET,
|
||||||
|
authority=s.MS_ENTRA_AUTHORITY
|
||||||
|
)
|
||||||
|
|
||||||
|
flow = msal_app.initiate_auth_code_flow(
|
||||||
|
scopes=s.MS_ENTRA_SCOPES,
|
||||||
|
redirect_uri=s.MS_ENTRA_REDIRECT_URI
|
||||||
|
)
|
||||||
|
|
||||||
|
request.session["msal_auth_flow"] = flow
|
||||||
|
return redirect(flow["auth_uri"])
|
||||||
|
|
||||||
|
|
||||||
|
def microsoft_callback(request):
|
||||||
|
msal_app = msal.ConfidentialClientApplication(
|
||||||
|
client_id=s.MS_ENTRA_CLIENT_ID,
|
||||||
|
client_credential=s.MS_ENTRA_CLIENT_SECRET,
|
||||||
|
authority=s.MS_ENTRA_AUTHORITY
|
||||||
|
)
|
||||||
|
|
||||||
|
flow = request.session.pop("msal_auth_flow", None)
|
||||||
|
if not flow:
|
||||||
|
return redirect("/")
|
||||||
|
|
||||||
|
# Acquire token using the flow and callback request
|
||||||
|
result = msal_app.acquire_token_by_auth_code_flow(flow, request.GET)
|
||||||
|
|
||||||
|
if "access_token" in result:
|
||||||
|
# Optional: Fetch user info from Microsoft Graph
|
||||||
|
import requests
|
||||||
|
resp = requests.get(
|
||||||
|
"https://graph.microsoft.com/v1.0/me",
|
||||||
|
headers={"Authorization": f"Bearer {result['access_token']}"}
|
||||||
|
)
|
||||||
|
user_info = resp.json()
|
||||||
|
|
||||||
|
user_name = user_info["displayName"]
|
||||||
|
user_email = user_info["mail"]
|
||||||
|
user_oid = user_info["id"]
|
||||||
|
|
||||||
|
# Get implementing class
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
if User.objects.filter(uuid=user_oid).exists():
|
||||||
|
login(request, User.objects.get(uuid=user_oid))
|
||||||
|
else:
|
||||||
|
u = UserManager.create_user(user_name, user_email, None, uuid=user_oid, is_active=True)
|
||||||
|
login(request, u)
|
||||||
|
|
||||||
|
# TODO Group Sync
|
||||||
|
|
||||||
|
return redirect("/")
|
||||||
|
|
||||||
|
return redirect("/") # Handle errors
|
||||||
0
epdb/__init__.py
Normal file
118
epdb/admin.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from .models import (
|
||||||
|
User,
|
||||||
|
UserPackagePermission,
|
||||||
|
Group,
|
||||||
|
GroupPackagePermission,
|
||||||
|
Package,
|
||||||
|
MLRelativeReasoning,
|
||||||
|
Compound,
|
||||||
|
CompoundStructure,
|
||||||
|
SimpleAmbitRule,
|
||||||
|
ParallelRule,
|
||||||
|
Reaction,
|
||||||
|
Pathway,
|
||||||
|
Node,
|
||||||
|
Edge,
|
||||||
|
Scenario,
|
||||||
|
Setting,
|
||||||
|
ExternalDatabase,
|
||||||
|
ExternalIdentifier,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UserPackagePermissionAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GroupAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GroupPackagePermissionAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class EPAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ["name", "description"]
|
||||||
|
|
||||||
|
|
||||||
|
class PackageAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MLRelativeReasoningAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CompoundAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CompoundStructureAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleAmbitRuleAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ParallelRuleAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ReactionAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PathwayAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NodeAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class EdgeAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ScenarioAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SettingAdmin(EPAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalDatabaseAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalIdentifierAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.register(User, UserAdmin)
|
||||||
|
admin.site.register(UserPackagePermission, UserPackagePermissionAdmin)
|
||||||
|
admin.site.register(Group, GroupAdmin)
|
||||||
|
admin.site.register(GroupPackagePermission, GroupPackagePermissionAdmin)
|
||||||
|
admin.site.register(Package, PackageAdmin)
|
||||||
|
admin.site.register(MLRelativeReasoning, MLRelativeReasoningAdmin)
|
||||||
|
admin.site.register(Compound, CompoundAdmin)
|
||||||
|
admin.site.register(CompoundStructure, CompoundStructureAdmin)
|
||||||
|
admin.site.register(SimpleAmbitRule, SimpleAmbitRuleAdmin)
|
||||||
|
admin.site.register(ParallelRule, ParallelRuleAdmin)
|
||||||
|
admin.site.register(Reaction, ReactionAdmin)
|
||||||
|
admin.site.register(Pathway, PathwayAdmin)
|
||||||
|
admin.site.register(Node, NodeAdmin)
|
||||||
|
admin.site.register(Edge, EdgeAdmin)
|
||||||
|
admin.site.register(Setting, SettingAdmin)
|
||||||
|
admin.site.register(Scenario, ScenarioAdmin)
|
||||||
|
admin.site.register(ExternalDatabase, ExternalDatabaseAdmin)
|
||||||
|
admin.site.register(ExternalIdentifier, ExternalIdentifierAdmin)
|
||||||
113
epdb/api.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from ninja import Router, Schema, Field
|
||||||
|
from ninja.errors import HttpError
|
||||||
|
from ninja.pagination import paginate
|
||||||
|
from ninja.security import HttpBearer
|
||||||
|
|
||||||
|
from .logic import PackageManager
|
||||||
|
from .models import User, Compound, APIToken
|
||||||
|
|
||||||
|
|
||||||
|
class BearerTokenAuth(HttpBearer):
|
||||||
|
def authenticate(self, request, token):
|
||||||
|
for token_obj in APIToken.objects.select_related("user").all():
|
||||||
|
if token_obj.check_token(token) and token_obj.is_valid():
|
||||||
|
return token_obj.user
|
||||||
|
raise HttpError(401, "Invalid or expired token")
|
||||||
|
|
||||||
|
|
||||||
|
def _anonymous_or_real(request):
|
||||||
|
if request.user.is_authenticated and not request.user.is_anonymous:
|
||||||
|
return request.user
|
||||||
|
return get_user_model().objects.get(username="anonymous")
|
||||||
|
|
||||||
|
|
||||||
|
router = Router(auth=BearerTokenAuth())
|
||||||
|
|
||||||
|
|
||||||
|
class UserSchema(Schema):
|
||||||
|
email: str
|
||||||
|
username: str
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
|
||||||
|
|
||||||
|
class PackageIn(Schema):
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
|
||||||
|
|
||||||
|
class PackageOut(Schema):
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
name: str
|
||||||
|
reviewed: bool
|
||||||
|
compound_links: str = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_compound_links(obj):
|
||||||
|
return f"{obj.url}/compound"
|
||||||
|
|
||||||
|
|
||||||
|
class Error(Schema):
|
||||||
|
message: str
|
||||||
|
|
||||||
|
|
||||||
|
class CompoundSchema(Schema):
|
||||||
|
name: str = Field(None, alias="name")
|
||||||
|
id: str = Field(None, alias="url")
|
||||||
|
smiles: str = Field(None, alias="default_structure.smiles")
|
||||||
|
reviewed: bool = Field(None, alias="package.reviewed")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/user", response={200: List[UserSchema], 403: Error})
|
||||||
|
def get_users(request):
|
||||||
|
return User.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/package", response={200: List[PackageOut], 403: Error})
|
||||||
|
def get_packages(request):
|
||||||
|
return PackageManager.get_all_readable_packages(request.user, include_reviewed=True)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/package", response=PackageOut)
|
||||||
|
def create_package(request, package: PackageIn):
|
||||||
|
user = request.auth
|
||||||
|
name = package.name.strip()
|
||||||
|
description = package.description.strip()
|
||||||
|
|
||||||
|
p = PackageManager.create_package(user, name, description=description)
|
||||||
|
return p
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/package/{uuid:package_uuid}", response={200: PackageOut, 403: Error})
|
||||||
|
def get_package(request, package_uuid):
|
||||||
|
try:
|
||||||
|
return PackageManager.get_package_by_id(request.auth, package_id=package_uuid)
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
"message": f"Getting Package with id {package_uuid} failed due to insufficient rights!"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/compound", response={200: List[CompoundSchema], 403: Error})
|
||||||
|
@paginate
|
||||||
|
def get_compounds(request):
|
||||||
|
qs = Compound.objects.none()
|
||||||
|
for p in PackageManager.get_reviewed_packages():
|
||||||
|
qs |= Compound.objects.filter(package=p)
|
||||||
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
"/package/{uuid:package_uuid}/compound", response={200: List[CompoundSchema], 403: Error}
|
||||||
|
)
|
||||||
|
@paginate
|
||||||
|
def get_package_compounds(request, package_uuid):
|
||||||
|
try:
|
||||||
|
p = PackageManager.get_package_by_id(request.auth, package_uuid)
|
||||||
|
return Compound.objects.filter(package=p)
|
||||||
|
except ValueError:
|
||||||
|
return 403, {
|
||||||
|
"message": f"Getting Compounds for Package with id {package_uuid} failed due to insufficient rights!"
|
||||||
|
}
|
||||||
9
epdb/apps.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class EPDBConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "epdb"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
import epdb.signals # noqa: F401
|
||||||
1240
epdb/legacy_api.py
Normal file
1684
epdb/logic.py
Normal file
0
epdb/management/__init__.py
Normal file
0
epdb/management/commands/__init__.py
Normal file
224
epdb/management/commands/bootstrap.py
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from django.conf import settings as s
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from epdb.logic import UserManager, GroupManager, PackageManager, SettingManager
|
||||||
|
from epdb.models import (
|
||||||
|
UserSettingPermission,
|
||||||
|
MLRelativeReasoning,
|
||||||
|
EnviFormer,
|
||||||
|
Permission,
|
||||||
|
User,
|
||||||
|
ExternalDatabase,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def create_users(self):
|
||||||
|
# Anonymous User
|
||||||
|
if not User.objects.filter(email="anon@envipath.com").exists():
|
||||||
|
anon = UserManager.create_user(
|
||||||
|
"anonymous",
|
||||||
|
"anon@envipath.com",
|
||||||
|
"SuperSafe",
|
||||||
|
is_active=True,
|
||||||
|
add_to_group=False,
|
||||||
|
set_setting=False,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
anon = User.objects.get(email="anon@envipath.com")
|
||||||
|
|
||||||
|
# Admin User
|
||||||
|
if not User.objects.filter(email="admin@envipath.com").exists():
|
||||||
|
admin = UserManager.create_user(
|
||||||
|
"admin",
|
||||||
|
"admin@envipath.com",
|
||||||
|
"SuperSafe",
|
||||||
|
is_active=True,
|
||||||
|
add_to_group=False,
|
||||||
|
set_setting=False,
|
||||||
|
)
|
||||||
|
admin.is_staff = True
|
||||||
|
admin.is_superuser = True
|
||||||
|
admin.save()
|
||||||
|
else:
|
||||||
|
admin = User.objects.get(email="admin@envipath.com")
|
||||||
|
|
||||||
|
# System Group
|
||||||
|
g = GroupManager.create_group(admin, "enviPath Users", "All enviPath Users")
|
||||||
|
g.public = True
|
||||||
|
g.save()
|
||||||
|
|
||||||
|
g.user_member.add(anon)
|
||||||
|
g.save()
|
||||||
|
|
||||||
|
anon.default_group = g
|
||||||
|
anon.save()
|
||||||
|
|
||||||
|
admin.default_group = g
|
||||||
|
admin.save()
|
||||||
|
|
||||||
|
if not User.objects.filter(email="user0@envipath.com").exists():
|
||||||
|
user0 = UserManager.create_user(
|
||||||
|
"user0",
|
||||||
|
"user0@envipath.com",
|
||||||
|
"SuperSafe",
|
||||||
|
is_active=True,
|
||||||
|
add_to_group=False,
|
||||||
|
set_setting=False,
|
||||||
|
)
|
||||||
|
user0.is_staff = True
|
||||||
|
user0.is_superuser = True
|
||||||
|
user0.save()
|
||||||
|
else:
|
||||||
|
user0 = User.objects.get(email="user0@envipath.com")
|
||||||
|
|
||||||
|
g.user_member.add(user0)
|
||||||
|
g.save()
|
||||||
|
|
||||||
|
user0.default_group = g
|
||||||
|
user0.save()
|
||||||
|
|
||||||
|
return anon, admin, g, user0
|
||||||
|
|
||||||
|
def import_package(self, data, owner):
|
||||||
|
return PackageManager.import_legacy_package(
|
||||||
|
data, owner, keep_ids=True, add_import_timestamp=False, trust_reviewed=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_default_setting(self, owner, packages):
|
||||||
|
s = SettingManager.create_setting(
|
||||||
|
owner,
|
||||||
|
name="Global Default Setting",
|
||||||
|
description="Global Default Setting containing BBD Rules and Max 30 Nodes and Max Depth of 8",
|
||||||
|
max_nodes=30,
|
||||||
|
max_depth=5,
|
||||||
|
rule_packages=packages,
|
||||||
|
model=None,
|
||||||
|
model_threshold=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
def populate_common_external_databases(self):
|
||||||
|
"""
|
||||||
|
Helper function to populate common external databases.
|
||||||
|
This can be called from a Django management command.
|
||||||
|
"""
|
||||||
|
databases = [
|
||||||
|
{
|
||||||
|
"name": "PubChem Compound",
|
||||||
|
"full_name": "PubChem Compound Database",
|
||||||
|
"description": "Chemical database of small organic molecules",
|
||||||
|
"base_url": "https://pubchem.ncbi.nlm.nih.gov",
|
||||||
|
"url_pattern": "https://pubchem.ncbi.nlm.nih.gov/compound/{id}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PubChem Substance",
|
||||||
|
"full_name": "PubChem Substance Database",
|
||||||
|
"description": "Database of chemical substances",
|
||||||
|
"base_url": "https://pubchem.ncbi.nlm.nih.gov",
|
||||||
|
"url_pattern": "https://pubchem.ncbi.nlm.nih.gov/substance/{id}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ChEBI",
|
||||||
|
"full_name": "Chemical Entities of Biological Interest",
|
||||||
|
"description": "Dictionary of molecular entities",
|
||||||
|
"base_url": "https://www.ebi.ac.uk/chebi",
|
||||||
|
"url_pattern": "https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:{id}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "RHEA",
|
||||||
|
"full_name": "RHEA Reaction Database",
|
||||||
|
"description": "Comprehensive resource of biochemical reactions",
|
||||||
|
"base_url": "https://www.rhea-db.org",
|
||||||
|
"url_pattern": "https://www.rhea-db.org/rhea/{id}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "KEGG Reaction",
|
||||||
|
"full_name": "KEGG Reaction Database",
|
||||||
|
"description": "Database of biochemical reactions",
|
||||||
|
"base_url": "https://www.genome.jp",
|
||||||
|
"url_pattern": "https://www.genome.jp/entry/{id}",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "UniProt",
|
||||||
|
"full_name": "MetaCyc Metabolic Pathway Database",
|
||||||
|
"description": "UniProt is a freely accessible database of protein sequence and functional information",
|
||||||
|
"base_url": "https://www.uniprot.org",
|
||||||
|
"url_pattern": 'https://www.uniprot.org/uniprotkb?query="{id}"',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
for db_info in databases:
|
||||||
|
ExternalDatabase.objects.get_or_create(name=db_info["name"], defaults=db_info)
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
# Create users
|
||||||
|
anon, admin, g, user0 = self.create_users()
|
||||||
|
|
||||||
|
self.populate_common_external_databases()
|
||||||
|
|
||||||
|
# Import Packages
|
||||||
|
packages = [
|
||||||
|
"EAWAG-BBD.json",
|
||||||
|
"EAWAG-SOIL.json",
|
||||||
|
"EAWAG-SLUDGE.json",
|
||||||
|
"EAWAG-SEDIMENT.json",
|
||||||
|
]
|
||||||
|
|
||||||
|
mapping = {}
|
||||||
|
for p in packages:
|
||||||
|
print(f"Importing {p}...")
|
||||||
|
package_data = json.loads(
|
||||||
|
open(
|
||||||
|
s.BASE_DIR / "fixtures" / "packages" / "2025-07-18" / p, encoding="utf-8"
|
||||||
|
).read()
|
||||||
|
)
|
||||||
|
imported_package = self.import_package(package_data, admin)
|
||||||
|
mapping[p.replace(".json", "")] = imported_package
|
||||||
|
|
||||||
|
setting = self.create_default_setting(admin, [mapping["EAWAG-BBD"]])
|
||||||
|
setting.public = True
|
||||||
|
setting.save()
|
||||||
|
setting.make_global_default()
|
||||||
|
|
||||||
|
for u in [anon, user0]:
|
||||||
|
u.default_setting = setting
|
||||||
|
u.save()
|
||||||
|
|
||||||
|
usp = UserSettingPermission()
|
||||||
|
usp.user = u
|
||||||
|
usp.setting = setting
|
||||||
|
usp.permission = Permission.READ[0]
|
||||||
|
usp.save()
|
||||||
|
|
||||||
|
# Create Model Package
|
||||||
|
pack = PackageManager.create_package(
|
||||||
|
admin,
|
||||||
|
"Public Prediction Models",
|
||||||
|
"Package to make Prediction Models publicly available",
|
||||||
|
)
|
||||||
|
pack.reviewed = True
|
||||||
|
pack.save()
|
||||||
|
|
||||||
|
# Create RR
|
||||||
|
ml_model = MLRelativeReasoning.create(
|
||||||
|
package=pack,
|
||||||
|
rule_packages=[mapping["EAWAG-BBD"]],
|
||||||
|
data_packages=[mapping["EAWAG-BBD"]],
|
||||||
|
eval_packages=[],
|
||||||
|
threshold=0.5,
|
||||||
|
name="ECC - BBD - T0.5",
|
||||||
|
description="ML Relative Reasoning",
|
||||||
|
)
|
||||||
|
|
||||||
|
ml_model.build_dataset()
|
||||||
|
ml_model.build_model()
|
||||||
|
|
||||||
|
# If available, create EnviFormerModel
|
||||||
|
if s.ENVIFORMER_PRESENT:
|
||||||
|
EnviFormer.create(pack, "EnviFormer - T0.5", "EnviFormer Model with Threshold 0.5", 0.5)
|
||||||
105
epdb/management/commands/create_ml_models.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
from django.conf import settings as s
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from epdb.models import MLRelativeReasoning, EnviFormer, Package
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""This command can be run with
|
||||||
|
`python manage.py create_ml_models [model_names] -d [data_packages] OPTIONAL: -e [eval_packages]`
|
||||||
|
For example, to train both EnviFormer and MLRelativeReasoning on BBD and SOIL and evaluate them on SLUDGE
|
||||||
|
the below command would be used:
|
||||||
|
`python manage.py create_ml_models enviformer mlrr -d bbd soil -e sludge
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"model_names",
|
||||||
|
nargs="+",
|
||||||
|
type=str,
|
||||||
|
help="The names of models to train. Options are: enviformer, mlrr",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-d", "--data-packages", nargs="+", type=str, help="Packages for training"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-e", "--eval-packages", nargs="*", type=str, help="Packages for evaluation", default=[]
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--rule-packages",
|
||||||
|
nargs="*",
|
||||||
|
type=str,
|
||||||
|
help="Rule Packages mandatory for MLRR",
|
||||||
|
default=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
# Find Public Prediction Models package to add new models to
|
||||||
|
try:
|
||||||
|
pack = Package.objects.filter(name="Public Prediction Models")[0]
|
||||||
|
bbd = Package.objects.filter(name="EAWAG-BBD")[0]
|
||||||
|
soil = Package.objects.filter(name="EAWAG-SOIL")[0]
|
||||||
|
sludge = Package.objects.filter(name="EAWAG-SLUDGE")[0]
|
||||||
|
sediment = Package.objects.filter(name="EAWAG-SEDIMENT")[0]
|
||||||
|
except IndexError:
|
||||||
|
raise IndexError(
|
||||||
|
"Can't find correct packages. They should be created with the bootstrap command"
|
||||||
|
)
|
||||||
|
|
||||||
|
def decode_packages(package_list):
|
||||||
|
"""Decode package strings into their respective packages"""
|
||||||
|
packages = []
|
||||||
|
for p in package_list:
|
||||||
|
p = p.lower()
|
||||||
|
if p == "bbd":
|
||||||
|
packages.append(bbd)
|
||||||
|
elif p == "soil":
|
||||||
|
packages.append(soil)
|
||||||
|
elif p == "sludge":
|
||||||
|
packages.append(sludge)
|
||||||
|
elif p == "sediment":
|
||||||
|
packages.append(sediment)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unknown package {p}")
|
||||||
|
return packages
|
||||||
|
|
||||||
|
# Iteratively create models in options["model_names"]
|
||||||
|
print(f"Creating models: {options['model_names']}")
|
||||||
|
data_packages = decode_packages(options["data_packages"])
|
||||||
|
eval_packages = decode_packages(options["eval_packages"])
|
||||||
|
rule_packages = decode_packages(options["rule_packages"])
|
||||||
|
for model_name in options["model_names"]:
|
||||||
|
model_name = model_name.lower()
|
||||||
|
if model_name == "enviformer" and s.ENVIFORMER_PRESENT:
|
||||||
|
model = EnviFormer.create(
|
||||||
|
pack,
|
||||||
|
data_packages=data_packages,
|
||||||
|
eval_packages=eval_packages,
|
||||||
|
threshold=0.5,
|
||||||
|
name="EnviFormer - T0.5",
|
||||||
|
description="EnviFormer transformer",
|
||||||
|
)
|
||||||
|
elif model_name == "mlrr":
|
||||||
|
model = MLRelativeReasoning.create(
|
||||||
|
package=pack,
|
||||||
|
rule_packages=rule_packages,
|
||||||
|
data_packages=data_packages,
|
||||||
|
eval_packages=eval_packages,
|
||||||
|
threshold=0.5,
|
||||||
|
name="ECC - BBD - T0.5",
|
||||||
|
description="ML Relative Reasoning",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Cannot create model of type {model_name}, unknown model type")
|
||||||
|
# Build the dataset for the model, train it, evaluate it and save it
|
||||||
|
print(f"Building dataset for {model_name}")
|
||||||
|
model.build_dataset()
|
||||||
|
print(f"Training {model_name}")
|
||||||
|
model.build_model()
|
||||||
|
print(f"Evaluating {model_name}")
|
||||||
|
model.evaluate_model()
|
||||||
|
print(f"Saving {model_name}")
|
||||||
|
model.save()
|
||||||
58
epdb/management/commands/import_external_identifiers.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
from csv import DictReader
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from epdb.models import Compound, CompoundStructure, Reaction, ExternalDatabase, ExternalIdentifier
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
STR_TO_MODEL = {
|
||||||
|
"Compound": Compound,
|
||||||
|
"CompoundStructure": CompoundStructure,
|
||||||
|
"Reaction": Reaction,
|
||||||
|
}
|
||||||
|
|
||||||
|
STR_TO_DATABASE = {
|
||||||
|
"ChEBI": ExternalDatabase.objects.get(name="ChEBI"),
|
||||||
|
"RHEA": ExternalDatabase.objects.get(name="RHEA"),
|
||||||
|
"KEGG Reaction": ExternalDatabase.objects.get(name="KEGG Reaction"),
|
||||||
|
"PubChem Compound": ExternalDatabase.objects.get(name="PubChem Compound"),
|
||||||
|
"PubChem Substance": ExternalDatabase.objects.get(name="PubChem Substance"),
|
||||||
|
}
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--data",
|
||||||
|
type=str,
|
||||||
|
help="Path of the ID Mapping file.",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--replace-host",
|
||||||
|
type=str,
|
||||||
|
help="Replace https://envipath.org/ with this host, e.g. http://localhost:8000/",
|
||||||
|
)
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
with open(options["data"]) as fh:
|
||||||
|
reader = DictReader(fh)
|
||||||
|
for row in reader:
|
||||||
|
clz = self.STR_TO_MODEL[row["model"]]
|
||||||
|
|
||||||
|
url = row["url"]
|
||||||
|
if options["replace_host"]:
|
||||||
|
url = url.replace("https://envipath.org/", options["replace_host"])
|
||||||
|
|
||||||
|
instance = clz.objects.get(url=url)
|
||||||
|
db = self.STR_TO_DATABASE[row["identifier_type"]]
|
||||||
|
|
||||||
|
ExternalIdentifier.objects.create(
|
||||||
|
content_object=instance,
|
||||||
|
database=db,
|
||||||
|
identifier_value=row["identifier_value"],
|
||||||
|
url=db.url_pattern.format(id=row["identifier_value"]),
|
||||||
|
is_primary=False,
|
||||||
|
)
|
||||||
29
epdb/management/commands/import_legacy_package.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from epdb.logic import PackageManager
|
||||||
|
from epdb.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--data",
|
||||||
|
type=str,
|
||||||
|
help="Path of the Package to import.",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--owner",
|
||||||
|
type=str,
|
||||||
|
help="Username of the desired Owner.",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
owner = User.objects.get(username=options["owner"])
|
||||||
|
package_data = json.load(open(options["data"]))
|
||||||
|
PackageManager.import_legacy_package(package_data, owner)
|
||||||
64
epdb/management/commands/localize_urls.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
from django.apps import apps
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from django.db.models import F, Value, TextField, JSONField
|
||||||
|
from django.db.models.functions import Replace, Cast
|
||||||
|
|
||||||
|
from epdb.models import EnviPathModel
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--old",
|
||||||
|
type=str,
|
||||||
|
help="Old Host, most likely https://envipath.org/",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--new",
|
||||||
|
type=str,
|
||||||
|
help="New Host, most likely http://localhost:8000/",
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
MODELS = [
|
||||||
|
"User",
|
||||||
|
"Group",
|
||||||
|
"Package",
|
||||||
|
"Compound",
|
||||||
|
"CompoundStructure",
|
||||||
|
"Pathway",
|
||||||
|
"Edge",
|
||||||
|
"Node",
|
||||||
|
"Reaction",
|
||||||
|
"SimpleAmbitRule",
|
||||||
|
"SimpleRDKitRule",
|
||||||
|
"ParallelRule",
|
||||||
|
"SequentialRule",
|
||||||
|
"Scenario",
|
||||||
|
"Setting",
|
||||||
|
"MLRelativeReasoning",
|
||||||
|
"RuleBasedRelativeReasoning",
|
||||||
|
"EnviFormer",
|
||||||
|
"ApplicabilityDomain",
|
||||||
|
"EnzymeLink",
|
||||||
|
]
|
||||||
|
for model in MODELS:
|
||||||
|
obj_cls = apps.get_model("epdb", model)
|
||||||
|
print(f"Localizing urls for {model}")
|
||||||
|
obj_cls.objects.update(
|
||||||
|
url=Replace(F("url"), Value(options["old"]), Value(options["new"]))
|
||||||
|
)
|
||||||
|
if issubclass(obj_cls, EnviPathModel):
|
||||||
|
obj_cls.objects.update(
|
||||||
|
kv=Cast(
|
||||||
|
Replace(
|
||||||
|
Cast(F("kv"), output_field=TextField()),
|
||||||
|
Value(options["old"]),
|
||||||
|
Value(options["new"]),
|
||||||
|
),
|
||||||
|
output_field=JSONField(),
|
||||||
|
)
|
||||||
|
)
|
||||||
0
epdb/middleware/__init__.py
Normal file
27
epdb/middleware/login_required_middleware.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
|
||||||
|
class LoginRequiredMiddleware:
|
||||||
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
self.exempt_urls = [
|
||||||
|
reverse("login"),
|
||||||
|
reverse("logout"),
|
||||||
|
reverse("admin:login"),
|
||||||
|
reverse("admin:index"),
|
||||||
|
] + getattr(settings, "LOGIN_EXEMPT_URLS", [])
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
if not request.user.is_authenticated:
|
||||||
|
path = request.path_info
|
||||||
|
if not any(path.startswith(url) for url in self.exempt_urls):
|
||||||
|
if request.method == "GET":
|
||||||
|
if request.get_full_path() and request.get_full_path() != "/":
|
||||||
|
return redirect(
|
||||||
|
f"{settings.LOGIN_URL}?next={quote(request.get_full_path())}"
|
||||||
|
)
|
||||||
|
return redirect(settings.LOGIN_URL)
|
||||||
|
return self.get_response(request)
|
||||||
594
epdb/migrations/0001_initial.py
Normal file
@ -0,0 +1,594 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-07-22 20:58
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import django.contrib.auth.models
|
||||||
|
import django.contrib.auth.validators
|
||||||
|
import django.contrib.postgres.fields
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
import model_utils.fields
|
||||||
|
import uuid
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Compound',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EPModel',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Permission',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('permission', models.CharField(choices=[('read', 'Read'), ('write', 'Write'), ('all', 'All')], max_length=32)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='License',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('link', models.URLField(verbose_name='link')),
|
||||||
|
('image_link', models.URLField(verbose_name='Image link')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Rule',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='User',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
|
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||||
|
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||||
|
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||||
|
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
|
||||||
|
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
||||||
|
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||||
|
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||||
|
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||||
|
('email', models.EmailField(max_length=254, unique=True)),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
||||||
|
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'user',
|
||||||
|
'verbose_name_plural': 'users',
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='APIToken',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('hashed_key', models.CharField(max_length=128, unique=True)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('expires_at', models.DateTimeField(blank=True, default=datetime.datetime(2025, 10, 20, 20, 58, 48, 351675, tzinfo=datetime.timezone.utc), null=True)),
|
||||||
|
('name', models.CharField(blank=True, help_text='Optional name for the token', max_length=100)),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CompoundStructure',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
('smiles', models.TextField(verbose_name='SMILES')),
|
||||||
|
('canonical_smiles', models.TextField(verbose_name='Canonical SMILES')),
|
||||||
|
('inchikey', models.TextField(max_length=27, verbose_name='InChIKey')),
|
||||||
|
('normalized_structure', models.BooleanField(default=False)),
|
||||||
|
('compound', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.compound')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compound',
|
||||||
|
name='default_structure',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='compound_default_structure', to='epdb.compoundstructure', verbose_name='Default Structure'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Edge',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EnviFormer',
|
||||||
|
fields=[
|
||||||
|
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||||
|
('threshold', models.FloatField(default=0.5)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.epmodel',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='PluginModel',
|
||||||
|
fields=[
|
||||||
|
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.epmodel',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RuleBaseRelativeReasoning',
|
||||||
|
fields=[
|
||||||
|
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.epmodel',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Group',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(verbose_name='Group name')),
|
||||||
|
('public', models.BooleanField(default=False, verbose_name='Public Group')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('group_member', models.ManyToManyField(related_name='groups_in_group', to='epdb.group', verbose_name='Group member')),
|
||||||
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Group Owner')),
|
||||||
|
('user_member', models.ManyToManyField(related_name='users_in_group', to=settings.AUTH_USER_MODEL, verbose_name='User members')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='default_group',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_group', to='epdb.group', verbose_name='Default Group'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Node',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
('depth', models.IntegerField(verbose_name='Node depth')),
|
||||||
|
('default_node_label', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='default_node_structure', to='epdb.compoundstructure', verbose_name='Default Node Label')),
|
||||||
|
('node_labels', models.ManyToManyField(related_name='node_structures', to='epdb.compoundstructure', verbose_name='All Node Labels')),
|
||||||
|
('out_edges', models.ManyToManyField(to='epdb.edge', verbose_name='Outgoing Edges')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edge',
|
||||||
|
name='end_nodes',
|
||||||
|
field=models.ManyToManyField(related_name='edge_products', to='epdb.node', verbose_name='End Nodes'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edge',
|
||||||
|
name='start_nodes',
|
||||||
|
field=models.ManyToManyField(related_name='edge_educts', to='epdb.node', verbose_name='Start Nodes'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Package',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('reviewed', models.BooleanField(default=False, verbose_name='Reviewstatus')),
|
||||||
|
('license', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.license', verbose_name='License')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='epmodel',
|
||||||
|
name='package',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compound',
|
||||||
|
name='package',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='default_package',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.package', verbose_name='Default Package'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SequentialRule',
|
||||||
|
fields=[
|
||||||
|
('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.rule')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.rule',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SimpleRule',
|
||||||
|
fields=[
|
||||||
|
('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.rule')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.rule',),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='package',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='polymorphic_ctype',
|
||||||
|
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Pathway',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='node',
|
||||||
|
name='pathway',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.pathway', verbose_name='belongs to'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edge',
|
||||||
|
name='pathway',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.pathway', verbose_name='belongs to'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Reaction',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('aliases', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), default=list, size=None, verbose_name='Aliases')),
|
||||||
|
('multi_step', models.BooleanField(verbose_name='Multistep Reaction')),
|
||||||
|
('medline_references', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), null=True, size=None, verbose_name='Medline References')),
|
||||||
|
('educts', models.ManyToManyField(related_name='reaction_educts', to='epdb.compoundstructure', verbose_name='Educts')),
|
||||||
|
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||||
|
('products', models.ManyToManyField(related_name='reaction_products', to='epdb.compoundstructure', verbose_name='Products')),
|
||||||
|
('rules', models.ManyToManyField(related_name='reaction_rule', to='epdb.rule', verbose_name='Rule')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edge',
|
||||||
|
name='edge_label',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.reaction', verbose_name='Edge label'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Scenario',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('scenario_date', models.CharField(default='No date', max_length=256)),
|
||||||
|
('scenario_type', models.CharField(default='Not specified', max_length=256)),
|
||||||
|
('additional_information', models.JSONField(verbose_name='Additional Information')),
|
||||||
|
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Package')),
|
||||||
|
('parent', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='epdb.scenario')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='reaction',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='pathway',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='node',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edge',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compoundstructure',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compound',
|
||||||
|
name='scenarios',
|
||||||
|
field=models.ManyToManyField(to='epdb.scenario', verbose_name='Attached Scenarios'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Setting',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('public', models.BooleanField(default=False)),
|
||||||
|
('global_default', models.BooleanField(default=False)),
|
||||||
|
('max_depth', models.IntegerField(default=5, verbose_name='Setting Max Depth')),
|
||||||
|
('max_nodes', models.IntegerField(default=30, verbose_name='Setting Max Number of Nodes')),
|
||||||
|
('model_threshold', models.FloatField(blank=True, default=0.25, null=True, verbose_name='Setting Model Threshold')),
|
||||||
|
('model', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.epmodel', verbose_name='Setting EPModel')),
|
||||||
|
('rule_packages', models.ManyToManyField(blank=True, related_name='setting_rule_packages', to='epdb.package', verbose_name='Setting Rule Packages')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='pathway',
|
||||||
|
name='setting',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='epdb.setting', verbose_name='Setting'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='default_setting',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.setting', verbose_name='The users default settings'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MLRelativeReasoning',
|
||||||
|
fields=[
|
||||||
|
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||||
|
('threshold', models.FloatField(default=0.5)),
|
||||||
|
('model_status', models.CharField(choices=[('INITIAL', 'Initial'), ('INITIALIZING', 'Model is initializing.'), ('BUILDING', 'Model is building.'), ('BUILT_NOT_EVALUATED', 'Model is built and can be used for predictions, Model is not evaluated yet.'), ('EVALUATING', 'Model is evaluating'), ('FINISHED', 'Model has finished building and evaluation.'), ('ERROR', 'Model has failed.')], default='INITIAL')),
|
||||||
|
('eval_results', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('data_packages', models.ManyToManyField(related_name='data_packages', to='epdb.package', verbose_name='Data Packages')),
|
||||||
|
('eval_packages', models.ManyToManyField(related_name='eval_packages', to='epdb.package', verbose_name='Evaluation Packages')),
|
||||||
|
('rule_packages', models.ManyToManyField(related_name='rule_packages', to='epdb.package', verbose_name='Rule Packages')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.epmodel',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ApplicabilityDomain',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('num_neighbours', models.FloatField(default=5)),
|
||||||
|
('reliability_threshold', models.FloatField(default=0.5)),
|
||||||
|
('local_compatibilty_threshold', models.FloatField(default=0.5)),
|
||||||
|
('model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.mlrelativereasoning')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SimpleAmbitRule',
|
||||||
|
fields=[
|
||||||
|
('simplerule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.simplerule')),
|
||||||
|
('smirks', models.TextField(verbose_name='SMIRKS')),
|
||||||
|
('reactant_filter_smarts', models.TextField(null=True, verbose_name='Reactant Filter SMARTS')),
|
||||||
|
('product_filter_smarts', models.TextField(null=True, verbose_name='Product Filter SMARTS')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.simplerule',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SimpleRDKitRule',
|
||||||
|
fields=[
|
||||||
|
('simplerule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.simplerule')),
|
||||||
|
('reaction_smarts', models.TextField(verbose_name='SMIRKS')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.simplerule',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SequentialRuleOrdering',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('order_index', models.IntegerField()),
|
||||||
|
('sequential_rule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.sequentialrule')),
|
||||||
|
('simple_rule', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.simplerule')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sequentialrule',
|
||||||
|
name='simple_rules',
|
||||||
|
field=models.ManyToManyField(through='epdb.SequentialRuleOrdering', to='epdb.simplerule', verbose_name='Simple rules'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ParallelRule',
|
||||||
|
fields=[
|
||||||
|
('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.rule')),
|
||||||
|
('simple_rules', models.ManyToManyField(to='epdb.simplerule', verbose_name='Simple rules')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
'base_manager_name': 'objects',
|
||||||
|
},
|
||||||
|
bases=('epdb.rule',),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='compound',
|
||||||
|
unique_together={('uuid', 'package')},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='GroupPackagePermission',
|
||||||
|
fields=[
|
||||||
|
('permission_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='epdb.permission')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||||
|
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.group', verbose_name='Permission to')),
|
||||||
|
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Permission on')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('package', 'group')},
|
||||||
|
},
|
||||||
|
bases=('epdb.permission',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserPackagePermission',
|
||||||
|
fields=[
|
||||||
|
('permission_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='epdb.permission')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||||
|
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.package', verbose_name='Permission on')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Permission to')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('package', 'user')},
|
||||||
|
},
|
||||||
|
bases=('epdb.permission',),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserSettingPermission',
|
||||||
|
fields=[
|
||||||
|
('permission_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='epdb.permission')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='UUID of this object')),
|
||||||
|
('setting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.setting', verbose_name='Permission on')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Permission to')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('setting', 'user')},
|
||||||
|
},
|
||||||
|
bases=('epdb.permission',),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-08-25 18:07
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
import model_utils.fields
|
||||||
|
import uuid
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
|
('epdb', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ExternalDatabase',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||||
|
('name', models.CharField(max_length=100, unique=True, verbose_name='Database Name')),
|
||||||
|
('full_name', models.CharField(blank=True, max_length=255, verbose_name='Full Database Name')),
|
||||||
|
('description', models.TextField(blank=True, verbose_name='Description')),
|
||||||
|
('base_url', models.URLField(blank=True, null=True, verbose_name='Base URL')),
|
||||||
|
('url_pattern', models.CharField(blank=True, help_text="URL pattern with {id} placeholder, e.g., 'https://pubchem.ncbi.nlm.nih.gov/compound/{id}'", max_length=500, verbose_name='URL Pattern')),
|
||||||
|
('is_active', models.BooleanField(default=True, verbose_name='Is Active')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'External Database',
|
||||||
|
'verbose_name_plural': 'External Databases',
|
||||||
|
'db_table': 'epdb_external_database',
|
||||||
|
'ordering': ['name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='apitoken',
|
||||||
|
options={'ordering': ['-created'], 'verbose_name': 'API Token', 'verbose_name_plural': 'API Tokens'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='edge',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='edge',
|
||||||
|
name='polymorphic_ctype',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='is_active',
|
||||||
|
field=models.BooleanField(default=True, help_text='Whether this token is active'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='modified',
|
||||||
|
field=model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='applicabilitydomain',
|
||||||
|
name='functional_groups',
|
||||||
|
field=models.JSONField(blank=True, default=dict, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlrelativereasoning',
|
||||||
|
name='app_domain',
|
||||||
|
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.applicabilitydomain'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='created',
|
||||||
|
field=model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='expires_at',
|
||||||
|
field=models.DateTimeField(blank=True, help_text='Token expiration time (null for no expiration)', null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='hashed_key',
|
||||||
|
field=models.CharField(help_text='SHA-256 hash of the token key', max_length=128, unique=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(help_text='Descriptive name for this token', max_length=100),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='apitoken',
|
||||||
|
name='user',
|
||||||
|
field=models.ForeignKey(help_text='User who owns this token', on_delete=django.db.models.deletion.CASCADE, related_name='api_tokens', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='applicabilitydomain',
|
||||||
|
name='num_neighbours',
|
||||||
|
field=models.IntegerField(default=5),
|
||||||
|
),
|
||||||
|
migrations.AlterModelTable(
|
||||||
|
name='apitoken',
|
||||||
|
table='epdb_api_token',
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ExternalIdentifier',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||||
|
('object_id', models.IntegerField()),
|
||||||
|
('identifier_value', models.CharField(max_length=255, verbose_name='Identifier Value')),
|
||||||
|
('url', models.URLField(blank=True, null=True, verbose_name='Direct URL')),
|
||||||
|
('is_primary', models.BooleanField(default=False, help_text='Mark this as the primary identifier for this database', verbose_name='Is Primary')),
|
||||||
|
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
|
||||||
|
('database', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='epdb.externaldatabase', verbose_name='External Database')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'External Identifier',
|
||||||
|
'verbose_name_plural': 'External Identifiers',
|
||||||
|
'db_table': 'epdb_external_identifier',
|
||||||
|
'indexes': [models.Index(fields=['content_type', 'object_id'], name='epdb_extern_content_b76813_idx'), models.Index(fields=['database', 'identifier_value'], name='epdb_extern_databas_486422_idx')],
|
||||||
|
'unique_together': {('content_type', 'object_id', 'database', 'identifier_value')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,228 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-08-26 17:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def populate_url(apps, schema_editor):
|
||||||
|
MODELS = [
|
||||||
|
'User',
|
||||||
|
'Group',
|
||||||
|
'Package',
|
||||||
|
'Compound',
|
||||||
|
'CompoundStructure',
|
||||||
|
'Pathway',
|
||||||
|
'Edge',
|
||||||
|
'Node',
|
||||||
|
'Reaction',
|
||||||
|
'SimpleAmbitRule',
|
||||||
|
'SimpleRDKitRule',
|
||||||
|
'ParallelRule',
|
||||||
|
'SequentialRule',
|
||||||
|
'Scenario',
|
||||||
|
'Setting',
|
||||||
|
'MLRelativeReasoning',
|
||||||
|
'EnviFormer',
|
||||||
|
'ApplicabilityDomain',
|
||||||
|
]
|
||||||
|
for model in MODELS:
|
||||||
|
obj_cls = apps.get_model("epdb", model)
|
||||||
|
for obj in obj_cls.objects.all():
|
||||||
|
obj.url = assemble_url(obj)
|
||||||
|
if obj.url is None:
|
||||||
|
raise ValueError(f"Could not assemble url for {obj}")
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
|
||||||
|
def assemble_url(obj):
|
||||||
|
from django.conf import settings as s
|
||||||
|
match obj.__class__.__name__:
|
||||||
|
case 'User':
|
||||||
|
return '{}/user/{}'.format(s.SERVER_URL, obj.uuid)
|
||||||
|
case 'Group':
|
||||||
|
return '{}/group/{}'.format(s.SERVER_URL, obj.uuid)
|
||||||
|
case 'Package':
|
||||||
|
return '{}/package/{}'.format(s.SERVER_URL, obj.uuid)
|
||||||
|
case 'Compound':
|
||||||
|
return '{}/compound/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'CompoundStructure':
|
||||||
|
return '{}/structure/{}'.format(obj.compound.url, obj.uuid)
|
||||||
|
case 'SimpleAmbitRule':
|
||||||
|
return '{}/simple-ambit-rule/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'SimpleRDKitRule':
|
||||||
|
return '{}/simple-rdkit-rule/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'ParallelRule':
|
||||||
|
return '{}/parallel-rule/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'SequentialRule':
|
||||||
|
return '{}/sequential-rule/{}'.format(obj.compound.url, obj.uuid)
|
||||||
|
case 'Reaction':
|
||||||
|
return '{}/reaction/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'Pathway':
|
||||||
|
return '{}/pathway/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'Node':
|
||||||
|
return '{}/node/{}'.format(obj.pathway.url, obj.uuid)
|
||||||
|
case 'Edge':
|
||||||
|
return '{}/edge/{}'.format(obj.pathway.url, obj.uuid)
|
||||||
|
case 'MLRelativeReasoning':
|
||||||
|
return '{}/model/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'EnviFormer':
|
||||||
|
return '{}/model/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'ApplicabilityDomain':
|
||||||
|
return '{}/model/{}/applicability-domain/{}'.format(obj.model.package.url, obj.model.uuid, obj.uuid)
|
||||||
|
case 'Scenario':
|
||||||
|
return '{}/scenario/{}'.format(obj.package.url, obj.uuid)
|
||||||
|
case 'Setting':
|
||||||
|
return '{}/setting/{}'.format(s.SERVER_URL, obj.uuid)
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"Unknown model {obj.__class__.__name__}")
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('epdb', '0002_externaldatabase_alter_apitoken_options_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='applicabilitydomain',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compound',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compoundstructure',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edge',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='epmodel',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='group',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='node',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='package',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='pathway',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='reaction',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='scenario',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='setting',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=False, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
|
||||||
|
migrations.RunPython(populate_url, reverse_code=migrations.RunPython.noop),
|
||||||
|
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='applicabilitydomain',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='compound',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='compoundstructure',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='edge',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='epmodel',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='group',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='node',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='package',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='pathway',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='reaction',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='rule',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='scenario',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='setting',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='user',
|
||||||
|
name='url',
|
||||||
|
field=models.TextField(null=True, unique=True, verbose_name='URL'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-09-09 09:21
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('epdb', '0001_squashed_0003_applicabilitydomain_url_compound_url_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='mlrelativereasoning',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mlrelativereasoning',
|
||||||
|
name='data_packages',
|
||||||
|
field=models.ManyToManyField(related_name='%(app_label)s_%(class)s_data_packages', to='epdb.package', verbose_name='Data Packages'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mlrelativereasoning',
|
||||||
|
name='eval_packages',
|
||||||
|
field=models.ManyToManyField(related_name='%(app_label)s_%(class)s_eval_packages', to='epdb.package', verbose_name='Evaluation Packages'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mlrelativereasoning',
|
||||||
|
name='rule_packages',
|
||||||
|
field=models.ManyToManyField(related_name='%(app_label)s_%(class)s_rule_packages', to='epdb.package', verbose_name='Rule Packages'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RuleBasedRelativeReasoning',
|
||||||
|
fields=[
|
||||||
|
('epmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='epdb.epmodel')),
|
||||||
|
('threshold', models.FloatField(default=0.5)),
|
||||||
|
('eval_results', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('model_status', models.CharField(choices=[('INITIAL', 'Initial'), ('INITIALIZING', 'Model is initializing.'), ('BUILDING', 'Model is building.'), ('BUILT_NOT_EVALUATED', 'Model is built and can be used for predictions, Model is not evaluated yet.'), ('EVALUATING', 'Model is evaluating'), ('FINISHED', 'Model has finished building and evaluation.'), ('ERROR', 'Model has failed.')], default='INITIAL')),
|
||||||
|
('min_count', models.IntegerField(default=10)),
|
||||||
|
('max_count', models.IntegerField(default=0)),
|
||||||
|
('app_domain', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.applicabilitydomain')),
|
||||||
|
('data_packages', models.ManyToManyField(related_name='%(app_label)s_%(class)s_data_packages', to='epdb.package', verbose_name='Data Packages')),
|
||||||
|
('eval_packages', models.ManyToManyField(related_name='%(app_label)s_%(class)s_eval_packages', to='epdb.package', verbose_name='Evaluation Packages')),
|
||||||
|
('rule_packages', models.ManyToManyField(related_name='%(app_label)s_%(class)s_rule_packages', to='epdb.package', verbose_name='Rule Packages')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
bases=('epdb.epmodel',),
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='RuleBaseRelativeReasoning',
|
||||||
|
),
|
||||||
|
]
|
||||||
18
epdb/migrations/0005_alter_group_group_member.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-09-11 06:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('epdb', '0004_alter_mlrelativereasoning_options_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='group',
|
||||||
|
name='group_member',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='groups_in_group', to='epdb.group', verbose_name='Group member'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-09-18 06:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('epdb', '0005_alter_group_group_member'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mlrelativereasoning',
|
||||||
|
name='multigen_eval',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rulebasedrelativereasoning',
|
||||||
|
name='multigen_eval',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-10-07 08:19
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('epdb', '0006_mlrelativereasoning_multigen_eval_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='enviformer',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='app_domain',
|
||||||
|
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.applicabilitydomain'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='data_packages',
|
||||||
|
field=models.ManyToManyField(related_name='%(app_label)s_%(class)s_data_packages', to='epdb.package', verbose_name='Data Packages'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='eval_packages',
|
||||||
|
field=models.ManyToManyField(related_name='%(app_label)s_%(class)s_eval_packages', to='epdb.package', verbose_name='Evaluation Packages'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='eval_results',
|
||||||
|
field=models.JSONField(blank=True, default=dict, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='model_status',
|
||||||
|
field=models.CharField(choices=[('INITIAL', 'Initial'), ('INITIALIZING', 'Model is initializing.'), ('BUILDING', 'Model is building.'), ('BUILT_NOT_EVALUATED', 'Model is built and can be used for predictions, Model is not evaluated yet.'), ('EVALUATING', 'Model is evaluating'), ('FINISHED', 'Model has finished building and evaluation.'), ('ERROR', 'Model has failed.')], default='INITIAL'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='multigen_eval',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='enviformer',
|
||||||
|
name='rule_packages',
|
||||||
|
field=models.ManyToManyField(related_name='%(app_label)s_%(class)s_rule_packages', to='epdb.package', verbose_name='Rule Packages'),
|
||||||
|
),
|
||||||
|
]
|
||||||
64
epdb/migrations/0008_enzymelink.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2025-10-10 06:58
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
import model_utils.fields
|
||||||
|
import uuid
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("epdb", "0007_alter_enviformer_options_enviformer_app_domain_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="EnzymeLink",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"created",
|
||||||
|
model_utils.fields.AutoCreatedField(
|
||||||
|
default=django.utils.timezone.now, editable=False, verbose_name="created"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"modified",
|
||||||
|
model_utils.fields.AutoLastModifiedField(
|
||||||
|
default=django.utils.timezone.now, editable=False, verbose_name="modified"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"uuid",
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4, unique=True, verbose_name="UUID of this object"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("name", models.TextField(default="no name", verbose_name="Name")),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(default="no description", verbose_name="Descriptions"),
|
||||||
|
),
|
||||||
|
("url", models.TextField(null=True, unique=True, verbose_name="URL")),
|
||||||
|
("kv", models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
("ec_number", models.TextField(verbose_name="EC Number")),
|
||||||
|
("classification_level", models.IntegerField(verbose_name="Classification Level")),
|
||||||
|
("linking_method", models.TextField(verbose_name="Linking Method")),
|
||||||
|
("edge_evidence", models.ManyToManyField(to="epdb.edge")),
|
||||||
|
("reaction_evidence", models.ManyToManyField(to="epdb.reaction")),
|
||||||
|
(
|
||||||
|
"rule",
|
||||||
|
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="epdb.rule"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
0
epdb/migrations/__init__.py
Normal file
3666
epdb/models.py
Normal file
37
epdb/signals.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings as s
|
||||||
|
from django.db import transaction
|
||||||
|
from django.db.models.signals import pre_delete, post_delete
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from epdb.models import Node, Edge, EPModel
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(pre_delete, sender=Node)
|
||||||
|
@transaction.atomic
|
||||||
|
def delete_orphan_edges(sender, instance, **kwargs):
|
||||||
|
# check if the node that is about to be deleted is the only start node
|
||||||
|
for edge in Edge.objects.filter(start_nodes=instance):
|
||||||
|
if edge.start_nodes.count() == 1:
|
||||||
|
edge.delete()
|
||||||
|
|
||||||
|
# same for end_nodes
|
||||||
|
for edge in Edge.objects.filter(end_nodes=instance):
|
||||||
|
# check if the node that is about to be deleted is the only start node
|
||||||
|
if edge.end_nodes.count() == 1:
|
||||||
|
edge.delete()
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_delete, sender=EPModel)
|
||||||
|
def delete_epmodel_files(sender, instance, **kwargs):
|
||||||
|
# Delete the files on disk for the deleted model
|
||||||
|
mod_uuid = str(instance.uuid)
|
||||||
|
|
||||||
|
for f in os.listdir(s.MODEL_DIR):
|
||||||
|
if f.startswith(mod_uuid):
|
||||||
|
logger.info(f"Deleting {os.path.join(s.MODEL_DIR, f)}")
|
||||||
|
os.remove(os.path.join(s.MODEL_DIR, f))
|
||||||
85
epdb/tasks.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
from epdb.models import Pathway, Node, EPModel, Setting
|
||||||
|
from epdb.logic import SPathway
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="background")
|
||||||
|
def mul(a, b):
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="predict")
|
||||||
|
def predict_simple(model_pk: int, smiles: str):
|
||||||
|
mod = EPModel.objects.get(id=model_pk)
|
||||||
|
res = mod.predict(smiles)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="background")
|
||||||
|
def send_registration_mail(user_pk: int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="model")
|
||||||
|
def build_model(model_pk: int):
|
||||||
|
mod = EPModel.objects.get(id=model_pk)
|
||||||
|
mod.build_dataset()
|
||||||
|
mod.build_model()
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="model")
|
||||||
|
def evaluate_model(model_pk: int):
|
||||||
|
mod = EPModel.objects.get(id=model_pk)
|
||||||
|
mod.evaluate_model()
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="model")
|
||||||
|
def retrain(model_pk: int):
|
||||||
|
mod = EPModel.objects.get(id=model_pk)
|
||||||
|
mod.retrain()
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(queue="predict")
|
||||||
|
def predict(
|
||||||
|
pw_pk: int, pred_setting_pk: int, limit: Optional[int] = None, node_pk: Optional[int] = None
|
||||||
|
) -> Pathway:
|
||||||
|
pw = Pathway.objects.get(id=pw_pk)
|
||||||
|
setting = Setting.objects.get(id=pred_setting_pk)
|
||||||
|
|
||||||
|
pw.kv.update(**{"status": "running"})
|
||||||
|
pw.save()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# regular prediction
|
||||||
|
if limit is not None:
|
||||||
|
spw = SPathway(prediction_setting=setting, persist=pw)
|
||||||
|
level = 0
|
||||||
|
while not spw.done:
|
||||||
|
spw.predict_step(from_depth=level)
|
||||||
|
level += 1
|
||||||
|
|
||||||
|
# break in case we are in incremental mode
|
||||||
|
if limit != -1:
|
||||||
|
if level >= limit:
|
||||||
|
break
|
||||||
|
|
||||||
|
elif node_pk is not None:
|
||||||
|
n = Node.objects.get(id=node_pk, pathway=pw)
|
||||||
|
spw = SPathway.from_pathway(pw)
|
||||||
|
spw.predict_step(from_node=n)
|
||||||
|
else:
|
||||||
|
raise ValueError("Neither limit nor node_pk given!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
pw.kv.update({"status": "failed"})
|
||||||
|
pw.save()
|
||||||
|
raise e
|
||||||
|
|
||||||
|
pw.kv.update(**{"status": "completed"})
|
||||||
|
pw.save()
|
||||||
0
epdb/templatetags/__init__.py
Normal file
8
epdb/templatetags/envipytags.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def classname(obj):
|
||||||
|
return obj.__class__.__name__
|
||||||
195
epdb/urls.py
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
from django.contrib.auth import views as auth_views
|
||||||
|
from django.urls import path, re_path
|
||||||
|
|
||||||
|
from . import views as v
|
||||||
|
|
||||||
|
UUID = "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# Home
|
||||||
|
re_path(r"^$", v.index, name="index"),
|
||||||
|
# Login
|
||||||
|
re_path(r"^login", v.login, name="login"),
|
||||||
|
re_path(r"^logout", v.logout, name="logout"),
|
||||||
|
re_path(r"^register", v.register, name="register"),
|
||||||
|
# Built-In views
|
||||||
|
path(
|
||||||
|
"password_reset/",
|
||||||
|
auth_views.PasswordResetView.as_view(template_name="static/password_reset_form.html"),
|
||||||
|
name="password_reset",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"password_reset/done/",
|
||||||
|
auth_views.PasswordResetDoneView.as_view(template_name="static/password_reset_done.html"),
|
||||||
|
name="password_reset_done",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"reset/<uidb64>/<token>/",
|
||||||
|
auth_views.PasswordResetConfirmView.as_view(
|
||||||
|
template_name="static/password_reset_confirm.html"
|
||||||
|
),
|
||||||
|
name="password_reset_confirm",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"reset/done/",
|
||||||
|
auth_views.PasswordResetCompleteView.as_view(
|
||||||
|
template_name="static/password_reset_complete.html"
|
||||||
|
),
|
||||||
|
name="password_reset_complete",
|
||||||
|
),
|
||||||
|
# Top level urls
|
||||||
|
re_path(r"^package$", v.packages, name="packages"),
|
||||||
|
re_path(r"^compound$", v.compounds, name="compounds"),
|
||||||
|
re_path(r"^rule$", v.rules, name="rules"),
|
||||||
|
re_path(r"^reaction$", v.reactions, name="reactions"),
|
||||||
|
re_path(r"^pathway$", v.pathways, name="pathways"),
|
||||||
|
re_path(r"^scenario$", v.scenarios, name="scenarios"),
|
||||||
|
re_path(r"^model$", v.models, name="model"),
|
||||||
|
re_path(r"^user$", v.users, name="users"),
|
||||||
|
re_path(r"^group$", v.groups, name="groups"),
|
||||||
|
re_path(r"^search$", v.search, name="search"),
|
||||||
|
# User Detail
|
||||||
|
re_path(rf"^user/(?P<user_uuid>{UUID})", v.user, name="user"),
|
||||||
|
# Group Detail
|
||||||
|
re_path(rf"^group/(?P<group_uuid>{UUID})$", v.group, name="group detail"),
|
||||||
|
# "in package" urls
|
||||||
|
re_path(rf"^package/(?P<package_uuid>{UUID})$", v.package, name="package detail"),
|
||||||
|
# Compound
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/compound$",
|
||||||
|
v.package_compounds,
|
||||||
|
name="package compound list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/compound/(?P<compound_uuid>{UUID})$",
|
||||||
|
v.package_compound,
|
||||||
|
name="package compound detail",
|
||||||
|
),
|
||||||
|
# Compound Structure
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/compound/(?P<compound_uuid>{UUID})/structure$",
|
||||||
|
v.package_compound_structures,
|
||||||
|
name="package compound structure list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/compound/(?P<compound_uuid>{UUID})/structure/(?P<structure_uuid>{UUID})$",
|
||||||
|
v.package_compound_structure,
|
||||||
|
name="package compound structure detail",
|
||||||
|
),
|
||||||
|
# Rule
|
||||||
|
re_path(rf"^package/(?P<package_uuid>{UUID})/rule$", v.package_rules, name="package rule list"),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/rule/(?P<rule_uuid>{UUID})$",
|
||||||
|
v.package_rule,
|
||||||
|
name="package rule detail",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/simple-ambit-rule/(?P<rule_uuid>{UUID})$",
|
||||||
|
v.package_rule,
|
||||||
|
name="package rule detail",
|
||||||
|
),
|
||||||
|
# re_path(
|
||||||
|
# rf"^package/(?P<package_uuid>{UUID})/simple-rdkit-rule/(?P<rule_uuid>{UUID})$",
|
||||||
|
# v.package_rule,
|
||||||
|
# name="package rule detail",
|
||||||
|
# ),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/parallel-rule/(?P<rule_uuid>{UUID})$",
|
||||||
|
v.package_rule,
|
||||||
|
name="package rule detail",
|
||||||
|
),
|
||||||
|
# re_path(
|
||||||
|
# rf"^package/(?P<package_uuid>{UUID})/sequential-rule/(?P<rule_uuid>{UUID})$",
|
||||||
|
# v.package_rule,
|
||||||
|
# name="package rule detail",
|
||||||
|
# ),
|
||||||
|
# EnzymeLinks
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/rule/(?P<rule_uuid>{UUID})/enzymelink/(?P<enzymelink_uuid>{UUID})$",
|
||||||
|
v.package_rule_enzymelink,
|
||||||
|
name="package rule enzymelink detail",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/simple-ambit-rule/(?P<rule_uuid>{UUID})/enzymelink/(?P<enzymelink_uuid>{UUID})$",
|
||||||
|
v.package_rule_enzymelink,
|
||||||
|
name="package rule enzymelink detail",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/parallel-rule/(?P<rule_uuid>{UUID})/enzymelink/(?P<enzymelink_uuid>{UUID})$",
|
||||||
|
v.package_rule_enzymelink,
|
||||||
|
name="package rule enzymelink detail",
|
||||||
|
),
|
||||||
|
# Reaction
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/reaction$",
|
||||||
|
v.package_reactions,
|
||||||
|
name="package reaction list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/reaction/(?P<reaction_uuid>{UUID})$",
|
||||||
|
v.package_reaction,
|
||||||
|
name="package reaction detail",
|
||||||
|
),
|
||||||
|
# # Pathway
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/pathway$",
|
||||||
|
v.package_pathways,
|
||||||
|
name="package pathway list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})$",
|
||||||
|
v.package_pathway,
|
||||||
|
name="package pathway detail",
|
||||||
|
),
|
||||||
|
# Pathway Nodes
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/node$",
|
||||||
|
v.package_pathway_nodes,
|
||||||
|
name="package pathway node list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/node/(?P<node_uuid>{UUID})$",
|
||||||
|
v.package_pathway_node,
|
||||||
|
name="package pathway node detail",
|
||||||
|
),
|
||||||
|
# Pathway Edges
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/edge$",
|
||||||
|
v.package_pathway_edges,
|
||||||
|
name="package pathway edge list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/edge/(?P<edge_uuid>{UUID})$",
|
||||||
|
v.package_pathway_edge,
|
||||||
|
name="package pathway edge detail",
|
||||||
|
),
|
||||||
|
# Scenario
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/scenario$",
|
||||||
|
v.package_scenarios,
|
||||||
|
name="package scenario list",
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/scenario/(?P<scenario_uuid>{UUID})$",
|
||||||
|
v.package_scenario,
|
||||||
|
name="package scenario detail",
|
||||||
|
),
|
||||||
|
# Model
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/model$", v.package_models, name="package model list"
|
||||||
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/model/(?P<model_uuid>{UUID})$",
|
||||||
|
v.package_model,
|
||||||
|
name="package model detail",
|
||||||
|
),
|
||||||
|
re_path(r"^setting$", v.settings, name="settings"),
|
||||||
|
re_path(rf"^setting/(?P<setting_uuid>{UUID})", v.setting, name="setting"),
|
||||||
|
re_path(r"^indigo/info$", v.indigo, name="indigo_info"),
|
||||||
|
re_path(r"^indigo/aromatize$", v.aromatize, name="indigo_aromatize"),
|
||||||
|
re_path(r"^indigo/dearomatize$", v.dearomatize, name="indigo_dearomatize"),
|
||||||
|
re_path(r"^indigo/layout$", v.layout, name="indigo_layout"),
|
||||||
|
re_path(r"^depict$", v.depict, name="depict"),
|
||||||
|
# OAuth Stuff
|
||||||
|
path("o/userinfo/", v.userinfo, name="oauth_userinfo"),
|
||||||
|
]
|
||||||
2769
epdb/views.py
Normal file
1
fixtures/Fixture_Package.json
Normal file
BIN
fixtures/ambit_rules.json.gz
Normal file
1
fixtures/migration_status_per_rule.json
Normal file
BIN
fixtures/models/2750eaca-bc13-4018-81c2-f7f9d94bc435_ds.pkl
Normal file
BIN
fixtures/models/2750eaca-bc13-4018-81c2-f7f9d94bc435_mod.pkl
Normal file
441171
fixtures/packages/2025-07-18/EAWAG-BBD.json
Normal file
284131
fixtures/packages/2025-07-18/EAWAG-SEDIMENT.json
Normal file
187048
fixtures/packages/2025-07-18/EAWAG-SLUDGE.json
Normal file
1574452
fixtures/packages/2025-07-18/EAWAG-SOIL.json
Normal file
8328
fixtures/packages/2025-07-18/external_identifiers.csv
Normal file
BIN
fixtures/test_fixtures.jsonl.gz
Normal file
BIN
fixtures/test_fixtures_incl_model.jsonl.gz
Normal file
22
manage.py
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'envipath.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
0
migration/__init__.py
Normal file
3
migration/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
migration/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class MigrationConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'migration'
|
||||||
0
migration/migrations/__init__.py
Normal file
3
migration/models.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
3
migration/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
16
migration/urls.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from django.urls import re_path
|
||||||
|
|
||||||
|
from . import views as v
|
||||||
|
|
||||||
|
UUID = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
re_path(rf'^migration$', v.migration, name='migration'),
|
||||||
|
re_path(rf'^migration/package/(?P<package_uuid>{UUID})/rule/(?P<rule_uuid>{UUID})$', v.migration_detail, name='migration detail'),
|
||||||
|
re_path(rf'^migration/package/(?P<package_uuid>{UUID})/simple-rule/(?P<rule_uuid>{UUID})$',v.migration_detail, name='migration detail'),
|
||||||
|
re_path(rf'^migration/package/(?P<package_uuid>{UUID})/simple-ambit-rule/(?P<rule_uuid>{UUID})$', v.migration_detail, name='migration detail'),
|
||||||
|
re_path(rf'^migration/package/(?P<package_uuid>{UUID})/simple-rdkit-rule/(?P<rule_uuid>{UUID})$', v.migration_detail, name='migration detail'),
|
||||||
|
re_path(rf'^migration/package/(?P<package_uuid>{UUID})/parallel-rule/(?P<rule_uuid>{UUID})$', v.migration_detail, name='migration detail'),
|
||||||
|
re_path(rf'^migration/package/(?P<package_uuid>{UUID})/sequential-rule/(?P<rule_uuid>{UUID})$', v.migration_detail, name='migration detail'),
|
||||||
|
re_path(rf'^migration/compare$', v.compare, name='compare'),
|
||||||
|
]
|
||||||
277
migration/views.py
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
import gzip
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.conf import settings as s
|
||||||
|
from django.http import HttpResponseNotAllowed
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
from epdb.logic import PackageManager
|
||||||
|
from epdb.models import Rule, SimpleAmbitRule, Package, CompoundStructure
|
||||||
|
from epdb.views import get_base_context, _anonymous_or_real
|
||||||
|
from utilities.chem import FormatConverter
|
||||||
|
|
||||||
|
|
||||||
|
from rdkit import Chem
|
||||||
|
from rdkit.Chem.MolStandardize import rdMolStandardize
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_smiles(smiles):
|
||||||
|
m1 = Chem.MolFromSmiles(smiles)
|
||||||
|
if m1 is None:
|
||||||
|
print("Couldnt read smi: ", smiles)
|
||||||
|
return smiles
|
||||||
|
Chem.RemoveStereochemistry(m1)
|
||||||
|
# Normalizer takes care of charge/tautomer/resonance standardization
|
||||||
|
normalizer = rdMolStandardize.Normalizer()
|
||||||
|
return Chem.MolToSmiles(normalizer.normalize(m1), canonical=True)
|
||||||
|
|
||||||
|
|
||||||
|
def run_both_engines(SMILES, SMIRKS):
|
||||||
|
from envipy_ambit import apply
|
||||||
|
|
||||||
|
ambit_res = apply(SMIRKS, SMILES)
|
||||||
|
# ambit_res, ambit_errors = FormatConverter.sanitize_smiles([str(s) for s in ambit_res])
|
||||||
|
|
||||||
|
ambit_res = list(
|
||||||
|
set(
|
||||||
|
[
|
||||||
|
normalize_smiles(str(x))
|
||||||
|
for x in FormatConverter.sanitize_smiles([str(s) for s in ambit_res])[0]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
products = FormatConverter.apply(SMILES, SMIRKS)
|
||||||
|
|
||||||
|
all_rdkit_prods = []
|
||||||
|
for ps in products:
|
||||||
|
for p in ps:
|
||||||
|
all_rdkit_prods.append(p)
|
||||||
|
|
||||||
|
all_rdkit_prods = list(set(all_rdkit_prods))
|
||||||
|
# all_rdkit_res, rdkit_errors = FormatConverter.sanitize_smiles(all_rdkit_prods)
|
||||||
|
all_rdkit_res = list(
|
||||||
|
set(
|
||||||
|
[
|
||||||
|
normalize_smiles(str(x))
|
||||||
|
for x in FormatConverter.sanitize_smiles(
|
||||||
|
[str(s) for s in all_rdkit_prods]
|
||||||
|
)[0]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# return ambit_res, ambit_errors, all_rdkit_res, rdkit_errors
|
||||||
|
return ambit_res, 0, all_rdkit_res, 0
|
||||||
|
|
||||||
|
|
||||||
|
def migration(request):
|
||||||
|
if request.method == "GET":
|
||||||
|
context = get_base_context(request)
|
||||||
|
|
||||||
|
if (
|
||||||
|
os.path.exists(s.BASE_DIR / "fixtures" / "migration_status_per_rule.json")
|
||||||
|
and request.GET.get("force") is None
|
||||||
|
):
|
||||||
|
migration_status = json.load(
|
||||||
|
open(s.BASE_DIR / "fixtures" / "migration_status_per_rule.json")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
BBD = Package.objects.get(
|
||||||
|
url="http://localhost:8000/package/32de3cf4-e3e6-4168-956e-32fa5ddb0ce1"
|
||||||
|
)
|
||||||
|
ALL_SMILES = [
|
||||||
|
cs.smiles
|
||||||
|
for cs in CompoundStructure.objects.filter(compound__package=BBD)
|
||||||
|
]
|
||||||
|
RULES = SimpleAmbitRule.objects.filter(package=BBD)
|
||||||
|
|
||||||
|
results = list()
|
||||||
|
num_rules = len(RULES)
|
||||||
|
success = 0
|
||||||
|
error = 0
|
||||||
|
total = 0
|
||||||
|
|
||||||
|
for i, r in enumerate(RULES):
|
||||||
|
logger.debug(f"\r{i + 1:03d}/{num_rules}")
|
||||||
|
res = True
|
||||||
|
for smiles in ALL_SMILES:
|
||||||
|
try:
|
||||||
|
ambit_res, _, rdkit_res, _ = run_both_engines(smiles, r.smirks)
|
||||||
|
|
||||||
|
res &= set(ambit_res) == set(rdkit_res)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"name": r.name,
|
||||||
|
"detail_url": s.SERVER_URL
|
||||||
|
+ "/migration/"
|
||||||
|
+ r.url.replace("https://envipath.org/", "").replace(
|
||||||
|
"http://localhost:8000/", ""
|
||||||
|
),
|
||||||
|
"id": str(r.uuid),
|
||||||
|
"url": r.url,
|
||||||
|
"status": res,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if res:
|
||||||
|
success += 1
|
||||||
|
else:
|
||||||
|
error += 1
|
||||||
|
|
||||||
|
total += 1
|
||||||
|
results = sorted(results, key=lambda x: (x["status"], x["name"]))
|
||||||
|
|
||||||
|
migration_status = {
|
||||||
|
"results": results,
|
||||||
|
"success": success,
|
||||||
|
"error": error,
|
||||||
|
"total": total,
|
||||||
|
}
|
||||||
|
|
||||||
|
json.dump(
|
||||||
|
migration_status,
|
||||||
|
open(s.BASE_DIR / "fixtures" / "migration_status_per_rule.json", "w"),
|
||||||
|
)
|
||||||
|
|
||||||
|
for r in migration_status["results"]:
|
||||||
|
r["detail_url"] = r["detail_url"].replace(
|
||||||
|
"http://localhost:8000", s.SERVER_URL
|
||||||
|
)
|
||||||
|
|
||||||
|
context.update(**migration_status)
|
||||||
|
|
||||||
|
return render(request, "migration.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def migration_detail(request, package_uuid, rule_uuid):
|
||||||
|
current_user = _anonymous_or_real(request)
|
||||||
|
|
||||||
|
if request.method == "GET":
|
||||||
|
context = get_base_context(request)
|
||||||
|
|
||||||
|
BBD = Package.objects.get(name="EAWAG-BBD")
|
||||||
|
STRUCTURES = CompoundStructure.objects.filter(compound__package=BBD)
|
||||||
|
rule = Rule.objects.get(package=BBD, uuid=rule_uuid)
|
||||||
|
|
||||||
|
bt_rule_name = rule.name
|
||||||
|
smirks = rule.smirks
|
||||||
|
|
||||||
|
res = True
|
||||||
|
results = []
|
||||||
|
|
||||||
|
all_prods = set()
|
||||||
|
for structure in STRUCTURES:
|
||||||
|
ambit_smiles, ambit_errors, rdkit_smiles, rdkit_errors = run_both_engines(
|
||||||
|
structure.smiles, smirks
|
||||||
|
)
|
||||||
|
|
||||||
|
for x in ambit_smiles:
|
||||||
|
all_prods.add(x)
|
||||||
|
|
||||||
|
# TODO mode "intersection"
|
||||||
|
# partial_res = (len(set(ambit_smiles).intersection(set(rdkit_smiles))) > 0) or (len(ambit_smiles) == 0)
|
||||||
|
# FAILED (failures=18)
|
||||||
|
|
||||||
|
# TODO mode = "full ambit"
|
||||||
|
# partial_res = len(set(ambit_smiles).intersection(set(rdkit_smiles))) == len(set(ambit_smiles))
|
||||||
|
# FAILED (failures=34)
|
||||||
|
|
||||||
|
# TODO mode = "equality"
|
||||||
|
partial_res = set(ambit_smiles) == set(rdkit_smiles)
|
||||||
|
# FAILED (failures=30)
|
||||||
|
|
||||||
|
if len(ambit_smiles) or len(rdkit_smiles):
|
||||||
|
temp = {
|
||||||
|
"url": structure.url,
|
||||||
|
"id": str(structure.uuid),
|
||||||
|
"name": structure.name,
|
||||||
|
"initial_smiles": structure.smiles,
|
||||||
|
"ambit_smiles": sorted(list(ambit_smiles)),
|
||||||
|
"rdkit_smiles": sorted(list(rdkit_smiles)),
|
||||||
|
"status": set(ambit_smiles) == set(rdkit_smiles),
|
||||||
|
}
|
||||||
|
detail = f"""
|
||||||
|
BT: {bt_rule_name}
|
||||||
|
SMIRKS: {smirks}
|
||||||
|
Compound: {structure.smiles}
|
||||||
|
Compound URL: {structure.url}
|
||||||
|
Num ambit: {len(set(ambit_smiles))}
|
||||||
|
Num rdkit: {len(set(rdkit_smiles))}
|
||||||
|
Num Intersection A: {len(set(ambit_smiles).intersection(set(rdkit_smiles)))}
|
||||||
|
Num Intersection B: {len(set(rdkit_smiles).intersection(set(ambit_smiles)))}
|
||||||
|
Difference A: {set(ambit_smiles).difference(set(rdkit_smiles))}
|
||||||
|
Difference B: {set(rdkit_smiles).difference(set(ambit_smiles))}
|
||||||
|
ambit products: {ambit_smiles}
|
||||||
|
rdkit products: {rdkit_smiles}
|
||||||
|
ambit_errors: {ambit_errors}
|
||||||
|
rdkit_errors: {rdkit_errors}
|
||||||
|
"""
|
||||||
|
|
||||||
|
temp["detail"] = "\n".join([x.strip() for x in detail.split("\n")])
|
||||||
|
|
||||||
|
results.append(temp)
|
||||||
|
|
||||||
|
res &= partial_res
|
||||||
|
|
||||||
|
results = sorted(results, key=lambda x: x["status"])
|
||||||
|
context["results"] = results
|
||||||
|
context["res"] = res
|
||||||
|
context["bt_rule_name"] = bt_rule_name
|
||||||
|
return render(request, "migration_detail.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def compare(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
|
||||||
|
if request.method == "GET":
|
||||||
|
context["smirks"] = (
|
||||||
|
"[#1,#6:6][#7;X3;!$(NC1CC1)!$([N][C]=O)!$([!#8]CNC=O):1]([#1,#6:7])[#6;A;X4:2][H:3]>>[#1,#6:6][#7;X3:1]([#1,#6:7])[H:3].[#6;A:2]=O"
|
||||||
|
)
|
||||||
|
context["smiles"] = (
|
||||||
|
"C(CC(=O)N[C@@H](CS[Se-])C(=O)NCC(=O)[O-])[C@@H](C(=O)[O-])N"
|
||||||
|
)
|
||||||
|
return render(request, "compare.html", context)
|
||||||
|
|
||||||
|
elif request.method == "POST":
|
||||||
|
smiles = request.POST.get("smiles")
|
||||||
|
smirks = request.POST.get("smirks")
|
||||||
|
|
||||||
|
from envipy_ambit import apply
|
||||||
|
|
||||||
|
ambit_res = apply(smirks, smiles)
|
||||||
|
ambit_res, _ = FormatConverter.sanitize_smiles([str(x) for x in ambit_res])
|
||||||
|
|
||||||
|
products = FormatConverter.apply(smiles, smirks)
|
||||||
|
|
||||||
|
all_rdkit_prods = []
|
||||||
|
for ps in products:
|
||||||
|
for p in ps:
|
||||||
|
all_rdkit_prods.append(p)
|
||||||
|
|
||||||
|
all_rdkit_prods = list(set(all_rdkit_prods))
|
||||||
|
|
||||||
|
rdkit_res, _ = FormatConverter.sanitize_smiles(all_rdkit_prods)
|
||||||
|
context["result"] = True
|
||||||
|
context["ambit_res"] = sorted(set(ambit_res))
|
||||||
|
context["rdkit_res"] = sorted(set(rdkit_res))
|
||||||
|
context["diff"] = sorted(set(ambit_res).difference(set(rdkit_res)))
|
||||||
|
context["smirks"] = smirks
|
||||||
|
context["smiles"] = smiles
|
||||||
|
|
||||||
|
r = SimpleAmbitRule.objects.filter(smirks=smirks)
|
||||||
|
|
||||||
|
if r.exists():
|
||||||
|
context["rule"] = r.first()
|
||||||
|
|
||||||
|
return render(request, "compare.html", context)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return HttpResponseNotAllowed(["GET", "POST"])
|
||||||
91
pyproject.toml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
[project]
|
||||||
|
name = "envipy"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = [
|
||||||
|
"celery>=5.5.2",
|
||||||
|
"django>=5.2.1",
|
||||||
|
"django-extensions>=4.1",
|
||||||
|
"django-model-utils>=5.0.0",
|
||||||
|
"django-ninja>=1.4.1",
|
||||||
|
"django-oauth-toolkit>=3.0.1",
|
||||||
|
"django-polymorphic>=4.1.0",
|
||||||
|
"enviformer",
|
||||||
|
"envipy-additional-information",
|
||||||
|
"envipy-ambit>=0.1.0",
|
||||||
|
"envipy-plugins",
|
||||||
|
"epam-indigo>=1.30.1",
|
||||||
|
"gunicorn>=23.0.0",
|
||||||
|
"networkx>=3.4.2",
|
||||||
|
"psycopg2-binary>=2.9.10",
|
||||||
|
"python-dotenv>=1.1.0",
|
||||||
|
"rdkit>=2025.3.2",
|
||||||
|
"redis>=6.1.0",
|
||||||
|
"requests>=2.32.3",
|
||||||
|
"scikit-learn>=1.6.1",
|
||||||
|
"sentry-sdk[django]>=2.32.0",
|
||||||
|
"setuptools>=80.8.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
enviformer = { git = "ssh://git@git.envipath.com/enviPath/enviformer.git", rev = "v0.1.2" }
|
||||||
|
envipy-plugins = { git = "ssh://git@git.envipath.com/enviPath/enviPy-plugins.git", rev = "v0.1.0" }
|
||||||
|
envipy-additional-information = { git = "ssh://git@git.envipath.com/enviPath/enviPy-additional-information.git", rev = "v0.1.7"}
|
||||||
|
envipy-ambit = { git = "ssh://git@git.envipath.com/enviPath/enviPy-ambit.git" }
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
ms-login = ["msal>=1.33.0"]
|
||||||
|
dev = [
|
||||||
|
"celery-stubs==0.1.3",
|
||||||
|
"django-stubs>=5.2.4",
|
||||||
|
"poethepoet>=0.37.0",
|
||||||
|
"pre-commit>=4.3.0",
|
||||||
|
"ruff>=0.13.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 100
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||||
|
fixable = ["ALL"]
|
||||||
|
# Allow unused variables when underscore-prefixed.
|
||||||
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
docstring-code-format = true
|
||||||
|
|
||||||
|
# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in selected subdirectories.
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"__init__.py" = ["E402"]
|
||||||
|
"**/{tests,docs,tools}/*" = ["E402"]
|
||||||
|
|
||||||
|
[tool.poe.tasks]
|
||||||
|
# Main tasks
|
||||||
|
setup = { sequence = ["db-up", "migrate", "bootstrap"], help = "Complete setup: start database, run migrations, and bootstrap data" }
|
||||||
|
dev = { cmd = "python manage.py runserver", help = "Start the development server", deps = ["db-up"] }
|
||||||
|
|
||||||
|
# Database tasks
|
||||||
|
db-up = { cmd = "docker compose -f docker-compose.dev.yml up -d", help = "Start PostgreSQL database using Docker Compose" }
|
||||||
|
db-down = { cmd = "docker compose -f docker-compose.dev.yml down", help = "Stop PostgreSQL database" }
|
||||||
|
|
||||||
|
# Full cleanup tasks
|
||||||
|
clean = { sequence = ["clean-db"], help = "Remove model files and database volumes (WARNING: destroys all data!)" }
|
||||||
|
clean-db = { cmd = "docker compose -f docker-compose.dev.yml down -v", help = "Removes the database container and volume." }
|
||||||
|
|
||||||
|
# Django tasks
|
||||||
|
migrate = { cmd = "python manage.py migrate", help = "Run database migrations" }
|
||||||
|
bootstrap = { shell = """
|
||||||
|
echo "Bootstrapping initial data..."
|
||||||
|
echo "This will take a bit ⏱️. Get yourself some coffee..."
|
||||||
|
python manage.py bootstrap
|
||||||
|
echo "✓ Bootstrap complete"
|
||||||
|
echo ""
|
||||||
|
echo "Default admin credentials:"
|
||||||
|
echo " Username: admin"
|
||||||
|
echo " Email: admin@envipath.com"
|
||||||
|
echo " Password: SuperSafe"
|
||||||
|
""", help = "Bootstrap initial data (anonymous user, packages, models)" }
|
||||||
|
shell = { cmd = "python manage.py shell", help = "Open Django shell" }
|
||||||
168
static/css/c3.css
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*-- Chart --*/
|
||||||
|
.c3 svg {
|
||||||
|
font: 10px sans-serif;
|
||||||
|
-webkit-tap-highlight-color: transparent; }
|
||||||
|
|
||||||
|
.c3 path, .c3 line {
|
||||||
|
fill: none;
|
||||||
|
stroke: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c3 text {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none; }
|
||||||
|
|
||||||
|
.c3-legend-item-tile,
|
||||||
|
.c3-xgrid-focus,
|
||||||
|
.c3-ygrid,
|
||||||
|
.c3-event-rect,
|
||||||
|
.c3-bars path {
|
||||||
|
shape-rendering: crispEdges; }
|
||||||
|
|
||||||
|
.c3-chart-arc path {
|
||||||
|
stroke: #fff; }
|
||||||
|
|
||||||
|
.c3-chart-arc text {
|
||||||
|
fill: #fff;
|
||||||
|
font-size: 13px; }
|
||||||
|
|
||||||
|
/*-- Axis --*/
|
||||||
|
/*-- Grid --*/
|
||||||
|
.c3-grid line {
|
||||||
|
stroke: #aaa; }
|
||||||
|
|
||||||
|
.c3-grid text {
|
||||||
|
fill: #aaa; }
|
||||||
|
|
||||||
|
.c3-xgrid, .c3-ygrid {
|
||||||
|
stroke-dasharray: 3 3; }
|
||||||
|
|
||||||
|
/*-- Text on Chart --*/
|
||||||
|
.c3-text.c3-empty {
|
||||||
|
fill: #808080;
|
||||||
|
font-size: 2em; }
|
||||||
|
|
||||||
|
/*-- Line --*/
|
||||||
|
.c3-line {
|
||||||
|
stroke-width: 1px; }
|
||||||
|
|
||||||
|
/*-- Point --*/
|
||||||
|
.c3-circle._expanded_ {
|
||||||
|
stroke-width: 1px;
|
||||||
|
stroke: white; }
|
||||||
|
|
||||||
|
.c3-selected-circle {
|
||||||
|
fill: white;
|
||||||
|
stroke-width: 2px; }
|
||||||
|
|
||||||
|
/*-- Bar --*/
|
||||||
|
.c3-bar {
|
||||||
|
stroke-width: 0; }
|
||||||
|
|
||||||
|
.c3-bar._expanded_ {
|
||||||
|
fill-opacity: 0.75; }
|
||||||
|
|
||||||
|
/*-- Focus --*/
|
||||||
|
.c3-target.c3-focused {
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
|
.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step {
|
||||||
|
stroke-width: 2px; }
|
||||||
|
|
||||||
|
.c3-target.c3-defocused {
|
||||||
|
opacity: 0.3 !important; }
|
||||||
|
|
||||||
|
/*-- Region --*/
|
||||||
|
.c3-region {
|
||||||
|
fill: steelblue;
|
||||||
|
fill-opacity: .1; }
|
||||||
|
|
||||||
|
/*-- Brush --*/
|
||||||
|
.c3-brush .extent {
|
||||||
|
fill-opacity: .1; }
|
||||||
|
|
||||||
|
/*-- Select - Drag --*/
|
||||||
|
/*-- Legend --*/
|
||||||
|
.c3-legend-item {
|
||||||
|
font-size: 12px; }
|
||||||
|
|
||||||
|
.c3-legend-item-hidden {
|
||||||
|
opacity: 0.15; }
|
||||||
|
|
||||||
|
.c3-legend-background {
|
||||||
|
opacity: 0.75;
|
||||||
|
fill: white;
|
||||||
|
stroke: lightgray;
|
||||||
|
stroke-width: 1; }
|
||||||
|
|
||||||
|
/*-- Title --*/
|
||||||
|
.c3-title {
|
||||||
|
font: 14px sans-serif; }
|
||||||
|
|
||||||
|
/*-- Tooltip --*/
|
||||||
|
.c3-tooltip-container {
|
||||||
|
z-index: 10; }
|
||||||
|
|
||||||
|
.c3-tooltip {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
empty-cells: show;
|
||||||
|
-webkit-box-shadow: 7px 7px 12px -9px #777777;
|
||||||
|
-moz-box-shadow: 7px 7px 12px -9px #777777;
|
||||||
|
box-shadow: 7px 7px 12px -9px #777777;
|
||||||
|
opacity: 0.9; }
|
||||||
|
|
||||||
|
.c3-tooltip tr {
|
||||||
|
border: 1px solid #CCC; }
|
||||||
|
|
||||||
|
.c3-tooltip th {
|
||||||
|
background-color: #aaa;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 2px 5px;
|
||||||
|
text-align: left;
|
||||||
|
color: #FFF; }
|
||||||
|
|
||||||
|
.c3-tooltip td {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 3px 6px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: 1px dotted #999; }
|
||||||
|
|
||||||
|
.c3-tooltip td > span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
margin-right: 6px; }
|
||||||
|
|
||||||
|
.c3-tooltip td.value {
|
||||||
|
text-align: right; }
|
||||||
|
|
||||||
|
/*-- Area --*/
|
||||||
|
.c3-area {
|
||||||
|
stroke-width: 0;
|
||||||
|
opacity: 0.2; }
|
||||||
|
|
||||||
|
/*-- Arc --*/
|
||||||
|
.c3-chart-arcs-title {
|
||||||
|
dominant-baseline: middle;
|
||||||
|
font-size: 1.3em; }
|
||||||
|
|
||||||
|
.c3-chart-arcs .c3-chart-arcs-background {
|
||||||
|
fill: #e0e0e0;
|
||||||
|
stroke: none; }
|
||||||
|
|
||||||
|
.c3-chart-arcs .c3-chart-arcs-gauge-unit {
|
||||||
|
fill: #000;
|
||||||
|
font-size: 16px; }
|
||||||
|
|
||||||
|
.c3-chart-arcs .c3-chart-arcs-gauge-max {
|
||||||
|
fill: #777; }
|
||||||
|
|
||||||
|
.c3-chart-arcs .c3-chart-arcs-gauge-min {
|
||||||
|
fill: #777; }
|
||||||
|
|
||||||
|
.c3-chart-arc .c3-gauge-value {
|
||||||
|
fill: #000;
|
||||||
|
/* font-size: 28px !important;*/ }
|
||||||
126
static/css/epp.css
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
.mini-submenu{
|
||||||
|
display:none;
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 9px;
|
||||||
|
/*position: relative;*/
|
||||||
|
width: 42px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-submenu:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-submenu .icon-bar {
|
||||||
|
border-radius: 1px;
|
||||||
|
display: block;
|
||||||
|
height: 2px;
|
||||||
|
width: 22px;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-submenu .icon-bar {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slide-submenu{
|
||||||
|
background: rgba(0, 0, 0, 0.45);
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#eductsdiv {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
#agentsdiv {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
#productsdiv {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
#actions {
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.fade .modal-dialog {
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-dialog-multiple {
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
width: 600px;
|
||||||
|
margin: 30px auto;
|
||||||
|
max-height: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-element{
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-dialog-pps{
|
||||||
|
position: relative;
|
||||||
|
display: table;
|
||||||
|
margin-left: 35%;
|
||||||
|
margin-right: 35%;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-dialog-pps-big{
|
||||||
|
position: relative;
|
||||||
|
display: table;
|
||||||
|
margin-left: 25%;
|
||||||
|
margin-right: 25%;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1220px) {
|
||||||
|
.navbar-header-framework {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.navbar-left-framework,.navbar-right-framework {
|
||||||
|
float: none !important;
|
||||||
|
}
|
||||||
|
.navbar-toggle-framework {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.navbar-collapse-framework {
|
||||||
|
border-top: 1px solid transparent;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
|
||||||
|
}
|
||||||
|
.navbar-fixed-top-framework {
|
||||||
|
top: 0;
|
||||||
|
border-width: 0 0 1px;
|
||||||
|
}
|
||||||
|
.navbar-collapse-framework.collapse {
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
.navbar-nav-framework {
|
||||||
|
float: none!important;
|
||||||
|
margin-top: 7.5px;
|
||||||
|
}
|
||||||
|
.navbar-nav-framework>li {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.navbar-nav-framework>li>a {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.collapse-framework.in{
|
||||||
|
display:block !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
static/images/UoA-Logo-Primary-RGB-Large.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
static/images/UoA-Logo-Primary-RGB-Reversed-Large.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
static/images/UoA-Logo-Primary-RGB-Reversed-Small.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/images/UoA-Logo-Primary-RGB-Small.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
static/images/ealogo.gif
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
static/images/enviPy-screenshot.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
static/images/favicon.ico
Normal file
|
After Width: | Height: | Size: 192 KiB |
225
static/images/logo-long.svg
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
version="1.1"
|
||||||
|
width="314.98749"
|
||||||
|
height="28.8125"
|
||||||
|
id="svg3004"
|
||||||
|
xml:space="preserve"><metadata
|
||||||
|
id="metadata3010"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs3008" /><g
|
||||||
|
transform="matrix(1.25,0,0,-1.25,0,28.8125)"
|
||||||
|
id="g3012"><g
|
||||||
|
transform="scale(0.1,0.1)"
|
||||||
|
id="g3014"><path
|
||||||
|
d="m 957.473,175.816 0,-4.296 -18.453,0 0,-48.614 -5.04,0 0,48.614 -18.378,0 0,4.296 41.871,0"
|
||||||
|
id="path3016"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 969.695,175.816 0,-22.968 31.425,0 0,22.968 5.04,0 0,-52.91 -5.04,0 0,25.637 -31.425,0 0,-25.637 -5.039,0 0,52.91 5.039,0"
|
||||||
|
id="path3018"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1055.58,175.816 0,-4.296 -31.49,0 0,-19.122 29.49,0 0,-4.293 -29.49,0 0,-20.898 31.87,0 0,-4.301 -36.91,0 0,52.91 36.53,0"
|
||||||
|
id="path3020"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1124.58,175.816 0,-4.296 -31.5,0 0,-19.122 29.49,0 0,-4.293 -29.49,0 0,-20.898 31.87,0 0,-4.301 -36.91,0 0,52.91 36.54,0"
|
||||||
|
id="path3022"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1139.76,175.816 30.83,-44.757 0.15,0 0,44.757 5.04,0 0,-52.91 -5.64,0 -30.82,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.63,0"
|
||||||
|
id="path3024"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1188.15,175.816 17.19,-47.355 0.15,0 17.06,47.355 5.34,0 -19.65,-52.91 -5.86,0 -19.56,52.91 5.33,0"
|
||||||
|
id="path3026"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1235.15,122.906 5.043,0 0,52.9102 -5.043,0 0,-52.9102 z"
|
||||||
|
id="path3028"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1277.3,150.691 c 1.54,0 2.99,0.243 4.38,0.711 1.39,0.469 2.59,1.145 3.63,2.036 1.04,0.886 1.86,1.968 2.48,3.222 0.63,1.258 0.92,2.703 0.92,4.336 0,3.262 -0.94,5.824 -2.81,7.703 -1.88,1.875 -4.74,2.821 -8.6,2.821 l -18.82,0 0,-20.829 18.82,0 z m 0.38,25.125 c 2.16,0 4.23,-0.269 6.19,-0.816 1.95,-0.543 3.65,-1.367 5.1,-2.48 1.46,-1.118 2.62,-2.54 3.49,-4.297 0.86,-1.758 1.29,-3.821 1.29,-6.192 0,-3.359 -0.86,-6.273 -2.6,-8.742 -1.72,-2.473 -4.29,-4.055 -7.69,-4.746 l 0,-0.145 c 1.73,-0.25 3.16,-0.703 4.29,-1.367 1.14,-0.668 2.06,-1.527 2.78,-2.558 0.72,-1.035 1.23,-2.239 1.56,-3.594 0.31,-1.363 0.53,-2.832 0.62,-4.41 0.05,-0.887 0.1,-1.977 0.16,-3.262 0.05,-1.285 0.15,-2.582 0.29,-3.891 0.15,-1.312 0.38,-2.543 0.71,-3.711 0.32,-1.156 0.74,-2.054 1.3,-2.699 l -5.56,0 c -0.29,0.496 -0.54,1.098 -0.7,1.809 -0.18,0.723 -0.31,1.461 -0.37,2.234 -0.08,0.762 -0.14,1.512 -0.2,2.254 -0.05,0.742 -0.1,1.387 -0.14,1.926 -0.09,1.875 -0.26,3.742 -0.49,5.598 -0.22,1.851 -0.69,3.503 -1.4,4.961 -0.72,1.46 -1.76,2.632 -3.11,3.523 -1.36,0.887 -3.23,1.281 -5.6,1.191 l -19.12,0 0,-23.496 -5.03,0 0,52.91 24.23,0"
|
||||||
|
id="path3030"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1308.46,140.879 c 0.77,-2.793 1.95,-5.289 3.56,-7.484 1.61,-2.2 3.66,-3.965 6.19,-5.301 2.52,-1.336 5.54,-2.004 9.04,-2.004 3.51,0 6.51,0.668 9,2.004 2.5,1.336 4.55,3.101 6.15,5.301 1.6,2.195 2.8,4.691 3.56,7.484 0.77,2.789 1.15,5.613 1.15,8.48 0,2.914 -0.38,5.758 -1.15,8.52 -0.76,2.769 -1.96,5.25 -3.56,7.449 -1.6,2.199 -3.65,3.969 -6.15,5.297 -2.49,1.336 -5.49,2.008 -9,2.008 -3.5,0 -6.52,-0.672 -9.04,-2.008 -2.53,-1.328 -4.58,-3.098 -6.19,-5.297 -1.61,-2.199 -2.79,-4.68 -3.56,-7.449 -0.75,-2.762 -1.15,-5.606 -1.15,-8.52 0,-2.867 0.4,-5.691 1.15,-8.48 z m -4.63,18.934 c 1.04,3.308 2.6,6.23 4.67,8.777 2.08,2.547 4.68,4.57 7.82,6.078 3.14,1.504 6.79,2.254 10.93,2.254 4.15,0 7.78,-0.75 10.89,-2.254 3.11,-1.508 5.71,-3.531 7.78,-6.078 2.08,-2.547 3.64,-5.469 4.67,-8.777 1.05,-3.313 1.56,-6.797 1.56,-10.454 0,-3.656 -0.51,-7.136 -1.56,-10.449 -1.03,-3.308 -2.59,-6.226 -4.67,-8.738 -2.07,-2.52 -4.67,-4.531 -7.78,-6.043 -3.11,-1.5 -6.74,-2.266 -10.89,-2.266 -4.14,0 -7.79,0.766 -10.93,2.266 -3.14,1.512 -5.74,3.523 -7.82,6.043 -2.07,2.512 -3.63,5.43 -4.67,8.738 -1.04,3.313 -1.54,6.793 -1.54,10.449 0,3.657 0.5,7.141 1.54,10.454"
|
||||||
|
id="path3032"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1367.77,175.816 30.84,-44.757 0.15,0 0,44.757 5.05,0 0,-52.91 -5.64,0 -30.83,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.62,0"
|
||||||
|
id="path3034"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1423.89,175.816 18.3,-46.386 18.22,46.386 7.41,0 0,-52.91 -5.03,0 0,45.723 -0.15,0 -18.09,-45.723 -4.74,0 -18.15,45.723 -0.15,0 0,-45.723 -5.04,0 0,52.91 7.42,0"
|
||||||
|
id="path3036"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1517.1,175.816 0,-4.296 -31.48,0 0,-19.122 29.48,0 0,-4.293 -29.48,0 0,-20.898 31.86,0 0,-4.301 -36.9,0 0,52.91 36.52,0"
|
||||||
|
id="path3038"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1532.29,175.816 30.82,-44.757 0.14,0 0,44.757 5.03,0 0,-52.91 -5.62,0 -30.81,44.754 -0.15,0 0,-44.754 -5.03,0 0,52.91 5.62,0"
|
||||||
|
id="path3040"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1617.34,175.816 0,-4.296 -18.44,0 0,-48.614 -5.04,0 0,48.614 -18.38,0 0,4.296 41.86,0"
|
||||||
|
id="path3042"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1647.8,143.656 -10.22,27.121 -10.6,-27.121 20.82,0 z m -7.18,32.16 20.74,-52.91 -5.4,0 -6.46,16.449 -24.07,0 -6.38,-16.449 -5.33,0 21.26,52.91 5.64,0"
|
||||||
|
id="path3044"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1673.44,175.816 0,-48.609 29.65,0 0,-4.301 -34.68,0 0,52.91 5.03,0"
|
||||||
|
id="path3046"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1769.74,165.254 c -1.02,1.605 -2.25,2.953 -3.71,4.043 -1.46,1.082 -3.06,1.914 -4.81,2.48 -1.76,0.567 -3.6,0.856 -5.52,0.856 -3.51,0 -6.53,-0.672 -9.05,-2.008 -2.52,-1.328 -4.58,-3.098 -6.18,-5.297 -1.61,-2.199 -2.8,-4.68 -3.56,-7.449 -0.77,-2.762 -1.15,-5.606 -1.15,-8.52 0,-2.867 0.38,-5.691 1.15,-8.48 0.76,-2.793 1.95,-5.289 3.56,-7.484 1.6,-2.2 3.66,-3.965 6.18,-5.301 2.52,-1.336 5.54,-2.004 9.05,-2.004 2.46,0 4.69,0.449 6.66,1.336 1.98,0.89 3.68,2.101 5.12,3.633 1.43,1.523 2.59,3.324 3.48,5.371 0.89,2.05 1.45,4.261 1.71,6.633 l 5.03,0 c -0.35,-3.258 -1.11,-6.204 -2.3,-8.821 -1.18,-2.617 -2.7,-4.84 -4.59,-6.664 -1.88,-1.824 -4.08,-3.238 -6.63,-4.223 -2.54,-0.992 -5.37,-1.492 -8.48,-1.492 -4.17,0 -7.81,0.766 -10.93,2.266 -3.15,1.512 -5.76,3.523 -7.83,6.043 -2.07,2.512 -3.62,5.43 -4.65,8.738 -1.04,3.313 -1.57,6.793 -1.57,10.449 0,3.657 0.53,7.141 1.57,10.454 1.03,3.308 2.58,6.23 4.65,8.777 2.07,2.547 4.68,4.57 7.83,6.078 3.12,1.504 6.76,2.254 10.93,2.254 2.52,0 4.97,-0.371 7.38,-1.106 2.39,-0.738 4.56,-1.843 6.51,-3.296 1.95,-1.461 3.58,-3.254 4.89,-5.372 1.3,-2.125 2.13,-4.574 2.47,-7.335 l -5.04,0 c -0.43,2.019 -1.16,3.839 -2.17,5.441"
|
||||||
|
id="path3048"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1791.01,140.879 c 0.76,-2.793 1.95,-5.289 3.56,-7.484 1.6,-2.2 3.66,-3.965 6.18,-5.301 2.52,-1.336 5.53,-2.004 9.04,-2.004 3.51,0 6.5,0.668 9.01,2.004 2.49,1.336 4.54,3.101 6.14,5.301 1.61,2.195 2.79,4.691 3.57,7.484 0.75,2.789 1.14,5.613 1.14,8.48 0,2.914 -0.39,5.758 -1.14,8.52 -0.78,2.769 -1.96,5.25 -3.57,7.449 -1.6,2.199 -3.65,3.969 -6.14,5.297 -2.51,1.336 -5.5,2.008 -9.01,2.008 -3.51,0 -6.52,-0.672 -9.04,-2.008 -2.52,-1.328 -4.58,-3.098 -6.18,-5.297 -1.61,-2.199 -2.8,-4.68 -3.56,-7.449 -0.78,-2.762 -1.16,-5.606 -1.16,-8.52 0,-2.867 0.38,-5.691 1.16,-8.48 z m -4.64,18.934 c 1.04,3.308 2.6,6.23 4.67,8.777 2.08,2.547 4.68,4.57 7.82,6.078 3.13,1.504 6.77,2.254 10.93,2.254 4.15,0 7.78,-0.75 10.89,-2.254 3.11,-1.508 5.72,-3.531 7.79,-6.078 2.07,-2.547 3.62,-5.469 4.66,-8.777 1.04,-3.313 1.56,-6.797 1.56,-10.454 0,-3.656 -0.52,-7.136 -1.56,-10.449 -1.04,-3.308 -2.59,-6.226 -4.66,-8.738 -2.07,-2.52 -4.68,-4.531 -7.79,-6.043 -3.11,-1.5 -6.74,-2.266 -10.89,-2.266 -4.16,0 -7.8,0.766 -10.93,2.266 -3.14,1.512 -5.74,3.523 -7.82,6.043 -2.07,2.512 -3.63,5.43 -4.67,8.738 -1.04,3.313 -1.56,6.793 -1.56,10.449 0,3.657 0.52,7.141 1.56,10.454"
|
||||||
|
id="path3050"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1850.33,175.816 30.82,-44.757 0.15,0 0,44.757 5.04,0 0,-52.91 -5.64,0 -30.82,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.64,0"
|
||||||
|
id="path3052"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1935.39,175.816 0,-4.296 -18.45,0 0,-48.614 -5.04,0 0,48.614 -18.37,0 0,4.296 41.86,0"
|
||||||
|
id="path3054"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1965.86,143.656 -10.23,27.121 -10.6,-27.121 20.83,0 z m -7.21,32.16 20.76,-52.91 -5.41,0 -6.44,16.449 -24.08,0 -6.38,-16.449 -5.33,0 21.26,52.91 5.62,0"
|
||||||
|
id="path3056"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1993.71,175.816 18.3,-46.386 18.24,46.386 7.41,0 0,-52.91 -5.04,0 0,45.723 -0.15,0 -18.09,-45.723 -4.73,0 -18.16,45.723 -0.14,0 0,-45.723 -5.05,0 0,52.91 7.41,0"
|
||||||
|
id="path3058"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2050.78,122.906 5.0273,0 0,52.9102 -5.0273,0 0,-52.9102 z"
|
||||||
|
id="path3060"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2074.63,175.816 30.83,-44.757 0.15,0 0,44.757 5.04,0 0,-52.91 -5.63,0 -30.83,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.63,0"
|
||||||
|
id="path3062"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2151.78,143.656 -10.24,27.121 -10.58,-27.121 20.82,0 z m -7.2,32.16 20.76,-52.91 -5.41,0 -6.45,16.449 -24.09,0 -6.36,-16.449 -5.34,0 21.27,52.91 5.62,0"
|
||||||
|
id="path3064"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2177.93,175.816 30.82,-44.757 0.16,0 0,44.757 5.05,0 0,-52.91 -5.64,0 -30.84,44.754 -0.14,0 0,-44.754 -5.04,0 0,52.91 5.63,0"
|
||||||
|
id="path3066"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2263.01,175.816 0,-4.296 -18.46,0 0,-48.614 -5.04,0 0,48.614 -18.38,0 0,4.296 41.88,0"
|
||||||
|
id="path3068"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 945.785,32.6602 c 1.875,0 3.656,0.1562 5.336,0.4804 1.676,0.3164 3.16,0.8985 4.445,1.7383 1.286,0.8477 2.301,1.9649 3.043,3.375 0.739,1.4102 1.11,3.1719 1.11,5.2969 0,3.4101 -1.203,5.9648 -3.602,7.668 -2.387,1.7031 -5.836,2.5585 -10.332,2.5585 l -17.344,0 0,-21.1171 17.344,0 z m 0,25.414 c 2.028,0 3.778,0.2344 5.262,0.711 1.48,0.4609 2.719,1.1015 3.711,1.9218 0.98,0.8125 1.726,1.7696 2.215,2.8555 0.5,1.082 0.742,2.2422 0.742,3.4766 0,6.6211 -3.977,9.9375 -11.93,9.9375 l -17.344,0 0,-18.9024 17.344,0 z m 0,23.1953 c 2.223,0 4.36,-0.2109 6.41,-0.6289 2.051,-0.4218 3.852,-1.1328 5.41,-2.1484 1.559,-1.0156 2.805,-2.3438 3.743,-4 0.937,-1.6563 1.406,-3.7227 1.406,-6.1914 0,-1.3867 -0.219,-2.7305 -0.668,-4.0391 -0.445,-1.3086 -1.074,-2.4961 -1.887,-3.5547 -0.808,-1.0625 -1.781,-1.9687 -2.89,-2.7031 -1.114,-0.7422 -2.36,-1.2617 -3.739,-1.5586 l 0,-0.1523 c 3.403,-0.4453 6.121,-1.8321 8.145,-4.1797 2.031,-2.3477 3.043,-5.25 3.043,-8.711 0,-0.8398 -0.074,-1.7851 -0.227,-2.8515 -0.144,-1.0625 -0.437,-2.1524 -0.886,-3.2617 -0.446,-1.1133 -1.086,-2.2149 -1.93,-3.2969 -0.836,-1.0859 -1.957,-2.0391 -3.363,-2.8516 -1.414,-0.8203 -3.141,-1.4883 -5.192,-2.0039 -2.051,-0.5195 -4.508,-0.7812 -7.375,-0.7812 l -22.379,0 0,52.914 22.379,0"
|
||||||
|
id="path3070"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 975.426,28.3555 5.04297,0 0,52.9141 -5.04297,0 0,-52.9141 z"
|
||||||
|
id="path3072"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 997.105,46.3281 c 0.762,-2.789 1.95,-5.2812 3.555,-7.4804 1.6,-2.1993 3.67,-3.9688 6.18,-5.2969 2.53,-1.3399 5.54,-2.0039 9.04,-2.0039 3.51,0 6.52,0.664 9.01,2.0039 2.5,1.3281 4.54,3.0976 6.15,5.2969 1.61,2.1992 2.79,4.6914 3.55,7.4804 0.77,2.793 1.16,5.6211 1.16,8.4844 0,2.918 -0.39,5.7578 -1.16,8.5273 -0.76,2.7618 -1.94,5.2461 -3.55,7.4454 -1.61,2.2031 -3.65,3.9648 -6.15,5.3007 -2.49,1.3321 -5.5,2 -9.01,2 -3.5,0 -6.51,-0.6679 -9.04,-2 -2.51,-1.3359 -4.58,-3.0976 -6.18,-5.3007 -1.605,-2.1993 -2.793,-4.6836 -3.555,-7.4454 -0.773,-2.7695 -1.152,-5.6093 -1.152,-8.5273 0,-2.8633 0.379,-5.6914 1.152,-8.4844 z m -4.632,18.9336 c 1.035,3.3125 2.59,6.2383 4.668,8.7813 2.074,2.5429 4.679,4.5742 7.819,6.0781 3.13,1.5078 6.77,2.2578 10.92,2.2578 4.15,0 7.79,-0.75 10.9,-2.2578 3.11,-1.5039 5.71,-3.5352 7.78,-6.0781 2.08,-2.543 3.63,-5.4688 4.67,-8.7813 1.04,-3.3047 1.56,-6.789 1.56,-10.4492 0,-3.6602 -0.52,-7.1406 -1.56,-10.4414 -1.04,-3.3164 -2.59,-6.2305 -4.67,-8.7461 -2.07,-2.5195 -4.67,-4.5312 -7.78,-6.0391 -3.11,-1.5039 -6.75,-2.2656 -10.9,-2.2656 -4.15,0 -7.79,0.7617 -10.92,2.2656 -3.14,1.5079 -5.745,3.5196 -7.819,6.0391 -2.078,2.5156 -3.633,5.4297 -4.668,8.7461 -1.035,3.3008 -1.559,6.7812 -1.559,10.4414 0,3.6602 0.524,7.1445 1.559,10.4492"
|
||||||
|
id="path3074"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1087.1,81.2695 0,-4.2929 -18.45,0 0,-48.6211 -5.04,0 0,48.6211 -18.38,0 0,4.2929 41.87,0"
|
||||||
|
id="path3076"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1118.15,56.1484 c 1.53,0 2.99,0.2383 4.37,0.7071 1.39,0.4687 2.6,1.1484 3.63,2.0351 1.04,0.8907 1.86,1.9688 2.49,3.2227 0.61,1.2617 0.93,2.7109 0.93,4.332 0,3.2656 -0.95,5.836 -2.82,7.7031 -1.88,1.8829 -4.75,2.8282 -8.6,2.8282 l -18.82,0 0,-20.8282 18.82,0 z m 0.37,25.1211 c 2.17,0 4.23,-0.2695 6.19,-0.8203 1.95,-0.539 3.65,-1.3633 5.11,-2.4765 1.46,-1.1133 2.62,-2.543 3.49,-4.3008 0.86,-1.7578 1.29,-3.8125 1.29,-6.1875 0,-3.3594 -0.86,-6.2696 -2.59,-8.7461 -1.73,-2.4688 -4.3,-4.0469 -7.71,-4.7383 l 0,-0.1484 c 1.73,-0.25 3.16,-0.7032 4.3,-1.3672 1.14,-0.668 2.06,-1.5235 2.78,-2.5586 0.71,-1.0391 1.23,-2.2344 1.55,-3.5977 0.33,-1.3593 0.54,-2.8281 0.63,-4.4062 0.05,-0.8867 0.1,-1.9766 0.15,-3.2656 0.05,-1.2852 0.15,-2.5782 0.3,-3.8868 0.15,-1.3125 0.38,-2.5468 0.71,-3.707 0.31,-1.1562 0.74,-2.0586 1.29,-2.707 l -5.56,0 c -0.29,0.5 -0.53,1.1015 -0.7,1.8203 -0.17,0.7187 -0.3,1.4531 -0.37,2.2265 -0.07,0.7618 -0.14,1.5118 -0.19,2.25 -0.04,0.7461 -0.1,1.3946 -0.15,1.9297 -0.1,1.875 -0.26,3.7461 -0.48,5.6016 -0.22,1.8555 -0.69,3.5 -1.41,4.9609 -0.71,1.4532 -1.75,2.6289 -3.11,3.5235 -1.36,0.8906 -3.22,1.2812 -5.59,1.1875 l -19.12,0 0,-23.5 -5.04,0 0,52.914 24.23,0"
|
||||||
|
id="path3078"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1174.25,49.1055 -10.23,27.125 -10.6,-27.125 20.83,0 z m -7.19,32.164 20.75,-52.914 -5.41,0 -6.45,16.457 -24.08,0 -6.38,-16.457 -5.33,0 21.27,52.914 5.63,0"
|
||||||
|
id="path3080"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1200.41,81.2695 30.83,-44.7617 0.15,0 0,44.7617 5.04,0 0,-52.914 -5.63,0 -30.84,44.7578 -0.15,0 0,-44.7578 -5.04,0 0,52.914 5.64,0"
|
||||||
|
id="path3082"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1252.87,38.9609 c 0.9,-1.8281 2.12,-3.289 3.67,-4.375 1.57,-1.0898 3.4,-1.8671 5.52,-2.3359 2.12,-0.4727 4.4,-0.7031 6.83,-0.7031 1.37,0 2.89,0.1914 4.52,0.5976 1.62,0.3907 3.14,1.0196 4.55,1.8828 1.42,0.8711 2.58,1.9727 3.52,3.336 0.94,1.3515 1.41,3.0039 1.41,4.9258 0,1.4843 -0.33,2.7695 -1.01,3.8593 -0.66,1.086 -1.53,1.9961 -2.58,2.7383 -1.07,0.7422 -2.24,1.3438 -3.53,1.8164 -1.28,0.4688 -2.55,0.8555 -3.78,1.1524 l -11.78,2.8789 c -1.54,0.4062 -3.02,0.8906 -4.49,1.4922 -1.44,0.5898 -2.72,1.375 -3.81,2.3672 -1.09,0.9843 -1.95,2.2031 -2.63,3.6289 -0.67,1.4336 -1,3.1875 -1,5.2617 0,1.289 0.25,2.7929 0.74,4.5234 0.49,1.7266 1.42,3.3594 2.79,4.8906 1.35,1.5274 3.21,2.8243 5.59,3.8907 2.37,1.0625 5.4,1.5898 9.1,1.5898 2.62,0 5.13,-0.3398 7.49,-1.0351 2.38,-0.6915 4.47,-1.7305 6.22,-3.1133 1.8,-1.3789 3.21,-3.0977 4.26,-5.1446 1.08,-2.0546 1.6,-4.4453 1.6,-7.1601 l -5.03,0 c -0.1,2.0351 -0.56,3.7969 -1.37,5.3047 -0.82,1.5039 -1.88,2.7617 -3.19,3.7773 -1.3,1.0117 -2.81,1.7852 -4.53,2.3008 -1.7,0.5195 -3.49,0.7773 -5.37,0.7773 -1.72,0 -3.39,-0.1914 -5,-0.5586 -1.61,-0.371 -3.01,-0.9609 -4.22,-1.7812 -1.21,-0.8164 -2.18,-1.8906 -2.93,-3.2227 -0.74,-1.332 -1.11,-2.9882 -1.11,-4.9648 0,-1.2305 0.22,-2.3086 0.64,-3.2227 0.42,-0.914 0.98,-1.6953 1.72,-2.332 0.75,-0.6484 1.61,-1.1601 2.56,-1.5547 0.98,-0.4023 1.99,-0.7226 3.08,-0.9687 l 12.9,-3.1875 c 1.88,-0.4883 3.64,-1.0938 5.3,-1.8164 1.65,-0.711 3.11,-1.6055 4.37,-2.6602 1.27,-1.0625 2.24,-2.3633 2.97,-3.8945 0.71,-1.5313 1.07,-3.3867 1.07,-5.5586 0,-0.5899 -0.07,-1.3828 -0.2,-2.3672 -0.11,-0.9922 -0.41,-2.0313 -0.87,-3.1523 -0.47,-1.1133 -1.14,-2.2344 -2,-3.3711 -0.87,-1.1368 -2.06,-2.1602 -3.56,-3.0782 -1.51,-0.9062 -3.37,-1.6562 -5.6,-2.2226 -2.22,-0.5586 -4.88,-0.8516 -8,-0.8516 -3.11,0 -6,0.3594 -8.68,1.0781 -2.65,0.7188 -4.94,1.8125 -6.81,3.2969 -1.88,1.4844 -3.32,3.3789 -4.34,5.707 -1,2.3204 -1.43,5.1055 -1.3,8.375 l 5.05,0 c -0.06,-2.7148 0.37,-4.9921 1.25,-6.8164"
|
||||||
|
id="path3084"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1331.72,81.2695 0,-4.2929 -28.53,0 0,-19.1211 25.35,0 0,-4.3008 -25.35,0 0,-25.1992 -5.04,0 0,52.914 33.57,0"
|
||||||
|
id="path3086"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1343.54,46.3281 c 0.78,-2.789 1.95,-5.2812 3.55,-7.4804 1.6,-2.1993 3.68,-3.9688 6.2,-5.2969 2.51,-1.3399 5.53,-2.0039 9.03,-2.0039 3.51,0 6.51,0.664 9.01,2.0039 2.5,1.3281 4.55,3.0976 6.15,5.2969 1.6,2.1992 2.78,4.6914 3.56,7.4804 0.76,2.793 1.15,5.6211 1.15,8.4844 0,2.918 -0.39,5.7578 -1.15,8.5273 -0.78,2.7618 -1.96,5.2461 -3.56,7.4454 -1.6,2.2031 -3.65,3.9648 -6.15,5.3007 -2.5,1.3321 -5.5,2 -9.01,2 -3.5,0 -6.52,-0.6679 -9.03,-2 -2.52,-1.3359 -4.6,-3.0976 -6.2,-5.3007 -1.6,-2.1993 -2.77,-4.6836 -3.55,-7.4454 -0.77,-2.7695 -1.14,-5.6093 -1.14,-8.5273 0,-2.8633 0.37,-5.6914 1.14,-8.4844 z m -4.63,18.9336 c 1.03,3.3125 2.59,6.2383 4.66,8.7813 2.09,2.5429 4.69,4.5742 7.82,6.0781 3.14,1.5078 6.79,2.2578 10.93,2.2578 4.15,0 7.8,-0.75 10.9,-2.2578 3.11,-1.5039 5.7,-3.5352 7.78,-6.0781 2.09,-2.543 3.63,-5.4688 4.66,-8.7813 1.04,-3.3047 1.57,-6.789 1.57,-10.4492 0,-3.6602 -0.53,-7.1406 -1.57,-10.4414 -1.03,-3.3164 -2.57,-6.2305 -4.66,-8.7461 -2.08,-2.5195 -4.67,-4.5312 -7.78,-6.0391 -3.1,-1.5039 -6.75,-2.2656 -10.9,-2.2656 -4.14,0 -7.79,0.7617 -10.93,2.2656 -3.13,1.5079 -5.73,3.5196 -7.82,6.0391 -2.07,2.5156 -3.63,5.4297 -4.66,8.7461 -1.04,3.3008 -1.56,6.7812 -1.56,10.4414 0,3.6602 0.52,7.1445 1.56,10.4492"
|
||||||
|
id="path3088"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1421.16,56.1484 c 1.54,0 3,0.2383 4.39,0.7071 1.37,0.4687 2.58,1.1484 3.62,2.0351 1.04,0.8907 1.87,1.9688 2.49,3.2227 0.61,1.2617 0.91,2.7109 0.91,4.332 0,3.2656 -0.93,5.836 -2.81,7.7031 -1.88,1.8829 -4.73,2.8282 -8.6,2.8282 l -18.83,0 0,-20.8282 18.83,0 z m 0.37,25.1211 c 2.18,0 4.24,-0.2695 6.18,-0.8203 1.96,-0.539 3.67,-1.3633 5.12,-2.4765 1.47,-1.1133 2.63,-2.543 3.49,-4.3008 0.86,-1.7578 1.3,-3.8125 1.3,-6.1875 0,-3.3594 -0.87,-6.2696 -2.6,-8.7461 -1.72,-2.4688 -4.3,-4.0469 -7.71,-4.7383 l 0,-0.1484 c 1.74,-0.25 3.17,-0.7032 4.3,-1.3672 1.13,-0.668 2.06,-1.5235 2.78,-2.5586 0.72,-1.0391 1.24,-2.2344 1.56,-3.5977 0.32,-1.3593 0.52,-2.8281 0.63,-4.4062 0.05,-0.8867 0.1,-1.9766 0.15,-3.2656 0.05,-1.2852 0.15,-2.5782 0.29,-3.8868 0.16,-1.3125 0.38,-2.5468 0.7,-3.707 0.33,-1.1562 0.76,-2.0586 1.3,-2.707 l -5.55,0 c -0.31,0.5 -0.54,1.1015 -0.71,1.8203 -0.17,0.7187 -0.29,1.4531 -0.37,2.2265 -0.08,0.7618 -0.13,1.5118 -0.18,2.25 -0.05,0.7461 -0.1,1.3946 -0.15,1.9297 -0.1,1.875 -0.25,3.7461 -0.48,5.6016 -0.22,1.8555 -0.7,3.5 -1.41,4.9609 -0.73,1.4532 -1.76,2.6289 -3.12,3.5235 -1.36,0.8906 -3.21,1.2812 -5.59,1.1875 l -19.13,0 0,-23.5 -5.03,0 0,52.914 24.23,0"
|
||||||
|
id="path3090"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1456.21,81.2695 18.3,-46.3906 18.24,46.3906 7.41,0 0,-52.914 -5.04,0 0,45.7265 -0.15,0 -18.08,-45.7265 -4.74,0 -18.17,45.7265 -0.13,0 0,-45.7265 -5.05,0 0,52.914 7.41,0"
|
||||||
|
id="path3092"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1541.21,49.1055 -10.22,27.125 -10.6,-27.125 20.82,0 z m -7.19,32.164 20.74,-52.914 -5.42,0 -6.42,16.457 -24.08,0 -6.38,-16.457 -5.33,0 21.27,52.914 5.62,0"
|
||||||
|
id="path3094"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1593,81.2695 0,-4.2929 -18.47,0 0,-48.6211 -5.04,0 0,48.6211 -18.37,0 0,4.2929 41.88,0"
|
||||||
|
id="path3096"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1600.55,28.3555 5.0391,0 0,52.9141 -5.0391,0 0,-52.9141 z"
|
||||||
|
id="path3098"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1622.23,46.3281 c 0.76,-2.789 1.94,-5.2812 3.55,-7.4804 1.6,-2.1993 3.67,-3.9688 6.19,-5.2969 2.52,-1.3399 5.53,-2.0039 9.04,-2.0039 3.5,0 6.5,0.664 9.01,2.0039 2.48,1.3281 4.54,3.0976 6.14,5.2969 1.61,2.1992 2.8,4.6914 3.56,7.4804 0.76,2.793 1.15,5.6211 1.15,8.4844 0,2.918 -0.39,5.7578 -1.15,8.5273 -0.76,2.7618 -1.95,5.2461 -3.56,7.4454 -1.6,2.2031 -3.66,3.9648 -6.14,5.3007 -2.51,1.3321 -5.51,2 -9.01,2 -3.51,0 -6.52,-0.6679 -9.04,-2 -2.52,-1.3359 -4.59,-3.0976 -6.19,-5.3007 -1.61,-2.1993 -2.79,-4.6836 -3.55,-7.4454 -0.77,-2.7695 -1.16,-5.6093 -1.16,-8.5273 0,-2.8633 0.39,-5.6914 1.16,-8.4844 z m -4.64,18.9336 c 1.03,3.3125 2.6,6.2383 4.68,8.7813 2.07,2.5429 4.67,4.5742 7.8,6.0781 3.14,1.5078 6.79,2.2578 10.94,2.2578 4.16,0 7.78,-0.75 10.88,-2.2578 3.13,-1.5039 5.72,-3.5352 7.8,-6.0781 2.07,-2.543 3.62,-5.4688 4.66,-8.7813 1.03,-3.3047 1.55,-6.789 1.55,-10.4492 0,-3.6602 -0.52,-7.1406 -1.55,-10.4414 -1.04,-3.3164 -2.59,-6.2305 -4.66,-8.7461 -2.08,-2.5195 -4.67,-4.5312 -7.8,-6.0391 -3.1,-1.5039 -6.72,-2.2656 -10.88,-2.2656 -4.15,0 -7.8,0.7617 -10.94,2.2656 -3.13,1.5079 -5.73,3.5196 -7.8,6.0391 -2.08,2.5156 -3.65,5.4297 -4.68,8.7461 -1.03,3.3008 -1.55,6.7812 -1.55,10.4414 0,3.6602 0.52,7.1445 1.55,10.4492"
|
||||||
|
id="path3100"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1681.55,81.2695 30.82,-44.7617 0.15,0 0,44.7617 5.04,0 0,-52.914 -5.64,0 -30.82,44.7578 -0.15,0 0,-44.7578 -5.03,0 0,52.914 5.63,0"
|
||||||
|
id="path3102"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1775.58,55.332 c 3.51,0 6.35,0.8946 8.52,2.6719 2.17,1.7774 3.26,4.4922 3.26,8.1484 0,3.6602 -1.09,6.3711 -3.26,8.1485 -2.17,1.7851 -5.01,2.6758 -8.52,2.6758 l -17.35,0 0,-21.6446 17.35,0 z m 1.12,25.9375 c 2.36,0 4.51,-0.3359 6.43,-0.9961 1.94,-0.6679 3.58,-1.6562 4.99,-2.9648 1.37,-1.3125 2.43,-2.9063 3.17,-4.7852 0.74,-1.875 1.11,-4.0039 1.11,-6.3711 0,-2.3671 -0.37,-4.4921 -1.11,-6.371 -0.74,-1.8829 -1.8,-3.4766 -3.17,-4.7852 -1.41,-1.3047 -3.05,-2.293 -4.99,-2.9609 -1.92,-0.6641 -4.07,-0.9961 -6.43,-0.9961 l -18.47,0 0,-22.6836 -5.04,0 0,52.914 23.51,0"
|
||||||
|
id="path3104"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1824.93,49.1055 -10.22,27.125 -10.6,-27.125 20.82,0 z m -7.19,32.164 20.76,-52.914 -5.41,0 -6.45,16.457 -24.09,0 -6.38,-16.457 -5.33,0 21.28,52.914 5.62,0"
|
||||||
|
id="path3106"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1876.73,81.2695 0,-4.2929 -18.45,0 0,-48.6211 -5.04,0 0,48.6211 -18.38,0 0,4.2929 41.87,0"
|
||||||
|
id="path3108"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1888.96,81.2695 0,-22.9687 31.41,0 0,22.9687 5.04,0 0,-52.914 -5.04,0 0,25.6445 -31.41,0 0,-25.6445 -5.04,0 0,52.914 5.04,0"
|
||||||
|
id="path3110"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 1938.38,81.2695 12.01,-46.3125 0.15,0 12.9,46.3125 6.3,0 12.96,-46.3125 0.15,0 12.07,46.3125 5.04,0 -14.59,-52.914 -5.34,0 -13.42,47.3515 -0.14,0 -13.34,-47.3515 -5.48,0 -14.67,52.914 5.4,0"
|
||||||
|
id="path3112"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2034.73,49.1055 -10.24,27.125 -10.59,-27.125 20.83,0 z m -7.2,32.164 20.75,-52.914 -5.41,0 -6.44,16.457 -24.09,0 -6.37,-16.457 -5.34,0 21.27,52.914 5.63,0"
|
||||||
|
id="path3114"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2043.84,81.2695 5.93,0 17.41,-26.8281 17.33,26.8281 6.01,0 -20.9,-31.125 0,-21.789 -5.04,0 0,21.789 -20.74,31.125"
|
||||||
|
id="path3116"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2144.01,56.1484 c 1.55,0 3,0.2383 4.38,0.7071 1.39,0.4687 2.6,1.1484 3.63,2.0351 1.05,0.8907 1.88,1.9688 2.48,3.2227 0.62,1.2617 0.93,2.7109 0.93,4.332 0,3.2656 -0.94,5.836 -2.81,7.7031 -1.89,1.8829 -4.75,2.8282 -8.61,2.8282 l -18.81,0 0,-20.8282 18.81,0 z m 0.38,25.1211 c 2.18,0 4.23,-0.2695 6.19,-0.8203 1.95,-0.539 3.66,-1.3633 5.1,-2.4765 1.47,-1.1133 2.63,-2.543 3.5,-4.3008 0.86,-1.7578 1.29,-3.8125 1.29,-6.1875 0,-3.3594 -0.86,-6.2696 -2.59,-8.7461 -1.73,-2.4688 -4.3,-4.0469 -7.7,-4.7383 l 0,-0.1484 c 1.72,-0.25 3.15,-0.7032 4.28,-1.3672 1.15,-0.668 2.07,-1.5235 2.79,-2.5586 0.72,-1.0391 1.24,-2.2344 1.55,-3.5977 0.32,-1.3593 0.54,-2.8281 0.63,-4.4062 0.05,-0.8867 0.1,-1.9766 0.15,-3.2656 0.05,-1.2852 0.15,-2.5782 0.29,-3.8868 0.15,-1.3125 0.39,-2.5468 0.71,-3.707 0.33,-1.1562 0.76,-2.0586 1.3,-2.707 l -5.55,0 c -0.3,0.5 -0.54,1.1015 -0.71,1.8203 -0.17,0.7187 -0.3,1.4531 -0.38,2.2265 -0.07,0.7618 -0.13,1.5118 -0.18,2.25 -0.04,0.7461 -0.1,1.3946 -0.15,1.9297 -0.1,1.875 -0.26,3.7461 -0.49,5.6016 -0.22,1.8555 -0.68,3.5 -1.39,4.9609 -0.73,1.4532 -1.76,2.6289 -3.13,3.5235 -1.35,0.8906 -3.21,1.2812 -5.59,1.1875 l -19.11,0 0,-23.5 -5.04,0 0,52.914 24.23,0"
|
||||||
|
id="path3118"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2208.34,81.2695 0,-4.2929 -31.49,0 0,-19.1211 29.49,0 0,-4.3008 -29.49,0 0,-20.8945 31.87,0 0,-4.3047 -36.91,0 0,52.914 36.53,0"
|
||||||
|
id="path3120"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2221.6,38.9609 c 0.9,-1.8281 2.13,-3.289 3.66,-4.375 1.58,-1.0898 3.4,-1.8671 5.53,-2.3359 2.12,-0.4727 4.41,-0.7031 6.82,-0.7031 1.38,0 2.9,0.1914 4.53,0.5976 1.62,0.3907 3.13,1.0196 4.55,1.8828 1.41,0.8711 2.58,1.9727 3.52,3.336 0.94,1.3515 1.4,3.0039 1.4,4.9258 0,1.4843 -0.32,2.7695 -0.99,3.8593 -0.66,1.086 -1.55,1.9961 -2.59,2.7383 -1.06,0.7422 -2.24,1.3438 -3.53,1.8164 -1.28,0.4688 -2.54,0.8555 -3.78,1.1524 l -11.77,2.8789 c -1.55,0.4062 -3.03,0.8906 -4.5,1.4922 -1.45,0.5898 -2.73,1.375 -3.82,2.3672 -1.08,0.9843 -1.95,2.2031 -2.62,3.6289 -0.66,1.4336 -1,3.1875 -1,5.2617 0,1.289 0.24,2.7929 0.74,4.5234 0.5,1.7266 1.42,3.3594 2.78,4.8906 1.36,1.5274 3.23,2.8243 5.59,3.8907 2.38,1.0625 5.41,1.5898 9.12,1.5898 2.61,0 5.11,-0.3398 7.48,-1.0351 2.37,-0.6915 4.46,-1.7305 6.24,-3.1133 1.77,-1.3789 3.19,-3.0977 4.24,-5.1446 1.08,-2.0546 1.6,-4.4453 1.6,-7.1601 l -5.03,0 c -0.1,2.0351 -0.55,3.7969 -1.38,5.3047 -0.81,1.5039 -1.87,2.7617 -3.18,3.7773 -1.31,1.0117 -2.82,1.7852 -4.53,2.3008 -1.71,0.5195 -3.48,0.7773 -5.37,0.7773 -1.73,0 -3.4,-0.1914 -5.01,-0.5586 -1.6,-0.371 -3,-0.9609 -4.21,-1.7812 -1.21,-0.8164 -2.19,-1.8906 -2.94,-3.2227 -0.74,-1.332 -1.1,-2.9882 -1.1,-4.9648 0,-1.2305 0.21,-2.3086 0.63,-3.2227 0.43,-0.914 0.99,-1.6953 1.73,-2.332 0.75,-0.6484 1.62,-1.1601 2.56,-1.5547 0.97,-0.4023 1.99,-0.7226 3.08,-0.9687 l 12.9,-3.1875 c 1.87,-0.4883 3.64,-1.0938 5.3,-1.8164 1.65,-0.711 3.11,-1.6055 4.37,-2.6602 1.26,-1.0625 2.24,-2.3633 2.97,-3.8945 0.71,-1.5313 1.07,-3.3867 1.07,-5.5586 0,-0.5899 -0.07,-1.3828 -0.2,-2.3672 -0.11,-0.9922 -0.41,-2.0313 -0.87,-3.1523 -0.48,-1.1133 -1.15,-2.2344 -2.01,-3.3711 -0.86,-1.1368 -2.05,-2.1602 -3.55,-3.0782 -1.5,-0.9062 -3.37,-1.6562 -5.6,-2.2226 -2.22,-0.5586 -4.89,-0.8516 -8.01,-0.8516 -3.11,0 -5.99,0.3594 -8.67,1.0781 -2.66,0.7188 -4.94,1.8125 -6.8,3.2969 -1.89,1.4844 -3.33,3.3789 -4.36,5.707 -0.99,2.3204 -1.43,5.1055 -1.29,8.375 l 5.04,0 c -0.05,-2.7148 0.38,-4.9921 1.26,-6.8164"
|
||||||
|
id="path3122"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2270.24,46.3281 c 0.79,-2.789 1.96,-5.2812 3.57,-7.4804 1.6,-2.1993 3.67,-3.9688 6.18,-5.2969 2.52,-1.3399 5.54,-2.0039 9.04,-2.0039 3.51,0 6.52,0.664 9.02,2.0039 2.49,1.3281 4.54,3.0976 6.15,5.2969 1.6,2.1992 2.77,4.6914 3.55,7.4804 0.77,2.793 1.15,5.6211 1.15,8.4844 0,2.918 -0.38,5.7578 -1.15,8.5273 -0.78,2.7618 -1.95,5.2461 -3.55,7.4454 -1.61,2.2031 -3.66,3.9648 -6.15,5.3007 -2.5,1.3321 -5.51,2 -9.02,2 -3.5,0 -6.52,-0.6679 -9.04,-2 -2.51,-1.3359 -4.58,-3.0976 -6.18,-5.3007 -1.61,-2.1993 -2.78,-4.6836 -3.57,-7.4454 -0.75,-2.7695 -1.13,-5.6093 -1.13,-8.5273 0,-2.8633 0.38,-5.6914 1.13,-8.4844 z m -4.62,18.9336 c 1.04,3.3125 2.59,6.2383 4.66,8.7813 2.09,2.5429 4.68,4.5742 7.83,6.0781 3.14,1.5078 6.78,2.2578 10.92,2.2578 4.15,0 7.8,-0.75 10.9,-2.2578 3.11,-1.5039 5.7,-3.5352 7.79,-6.0781 2.07,-2.543 3.63,-5.4688 4.66,-8.7813 1.04,-3.3047 1.56,-6.789 1.56,-10.4492 0,-3.6602 -0.52,-7.1406 -1.56,-10.4414 -1.03,-3.3164 -2.59,-6.2305 -4.66,-8.7461 -2.09,-2.5195 -4.68,-4.5312 -7.79,-6.0391 -3.1,-1.5039 -6.75,-2.2656 -10.9,-2.2656 -4.14,0 -7.78,0.7617 -10.92,2.2656 -3.15,1.5079 -5.74,3.5196 -7.83,6.0391 -2.07,2.5156 -3.62,5.4297 -4.66,8.7461 -1.04,3.3008 -1.56,6.7812 -1.56,10.4414 0,3.6602 0.52,7.1445 1.56,10.4492"
|
||||||
|
id="path3124"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2328.53,81.2695 0,-32.7539 c 0,-3.0625 0.35,-5.664 1.03,-7.8242 0.69,-2.1406 1.71,-3.8984 3.05,-5.2578 1.33,-1.3555 2.97,-2.3477 4.88,-2.9648 1.93,-0.6172 4.11,-0.9219 6.52,-0.9219 2.47,0 4.67,0.3047 6.61,0.9219 1.93,0.6171 3.55,1.6093 4.88,2.9648 1.34,1.3594 2.35,3.1172 3.04,5.2578 0.69,2.1602 1.04,4.7617 1.04,7.8242 l 0,32.7539 5.04,0 0,-33.8672 c 0,-2.7148 -0.38,-5.2968 -1.14,-7.7382 -0.77,-2.4493 -1.99,-4.5899 -3.65,-6.418 -1.66,-1.8242 -3.76,-3.2695 -6.36,-4.332 -2.6,-1.0586 -5.74,-1.5938 -9.46,-1.5938 -3.65,0 -6.77,0.5352 -9.37,1.5938 -2.59,1.0625 -4.71,2.5078 -6.37,4.332 -1.66,1.8281 -2.87,3.9687 -3.63,6.418 -0.77,2.4414 -1.13,5.0234 -1.13,7.7382 l 0,33.8672 5.02,0"
|
||||||
|
id="path3126"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2400.87,56.1484 c 1.51,0 2.99,0.2383 4.36,0.7071 1.39,0.4687 2.59,1.1484 3.63,2.0351 1.03,0.8907 1.86,1.9688 2.49,3.2227 0.62,1.2617 0.92,2.7109 0.92,4.332 0,3.2656 -0.94,5.836 -2.82,7.7031 -1.86,1.8829 -4.73,2.8282 -8.58,2.8282 l -18.83,0 0,-20.8282 18.83,0 z m 0.36,25.1211 c 2.18,0 4.23,-0.2695 6.2,-0.8203 1.94,-0.539 3.64,-1.3633 5.11,-2.4765 1.45,-1.1133 2.61,-2.543 3.47,-4.3008 0.88,-1.7578 1.29,-3.8125 1.29,-6.1875 0,-3.3594 -0.85,-6.2696 -2.58,-8.7461 -1.73,-2.4688 -4.29,-4.0469 -7.71,-4.7383 l 0,-0.1484 c 1.73,-0.25 3.17,-0.7032 4.31,-1.3672 1.11,-0.668 2.05,-1.5235 2.77,-2.5586 0.71,-1.0391 1.23,-2.2344 1.55,-3.5977 0.32,-1.3593 0.52,-2.8281 0.63,-4.4062 0.05,-0.8867 0.11,-1.9766 0.16,-3.2656 0.04,-1.2852 0.15,-2.5782 0.29,-3.8868 0.14,-1.3125 0.38,-2.5468 0.7,-3.707 0.31,-1.1562 0.75,-2.0586 1.3,-2.707 l -5.56,0 c -0.29,0.5 -0.53,1.1015 -0.71,1.8203 -0.16,0.7187 -0.29,1.4531 -0.36,2.2265 -0.09,0.7618 -0.14,1.5118 -0.19,2.25 -0.05,0.7461 -0.1,1.3946 -0.15,1.9297 -0.09,1.875 -0.27,3.7461 -0.47,5.6016 -0.23,1.8555 -0.69,3.5 -1.42,4.9609 -0.71,1.4532 -1.75,2.6289 -3.1,3.5235 -1.37,0.8906 -3.23,1.2812 -5.6,1.1875 l -19.12,0 0,-23.5 -5.04,0 0,52.914 24.23,0"
|
||||||
|
id="path3128"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2465.16,70.7109 c -1.02,1.6094 -2.27,2.9493 -3.71,4.0391 -1.47,1.0859 -3.08,1.9141 -4.82,2.4844 -1.75,0.5625 -3.59,0.8515 -5.53,0.8515 -3.5,0 -6.51,-0.6679 -9.03,-2 -2.52,-1.3359 -4.6,-3.0976 -6.18,-5.3007 -1.62,-2.1993 -2.8,-4.6836 -3.58,-7.4454 -0.76,-2.7695 -1.14,-5.6093 -1.14,-8.5273 0,-2.8633 0.38,-5.6914 1.14,-8.4844 0.78,-2.789 1.96,-5.2812 3.58,-7.4804 1.58,-2.1993 3.66,-3.9688 6.18,-5.2969 2.52,-1.3399 5.53,-2.0039 9.03,-2.0039 2.47,0 4.7,0.4453 6.66,1.332 2,0.8906 3.7,2.1016 5.13,3.6289 1.44,1.5274 2.6,3.3281 3.48,5.3711 0.9,2.0508 1.46,4.2695 1.71,6.6367 l 5.04,0 c -0.35,-3.2578 -1.13,-6.1953 -2.3,-8.8203 -1.19,-2.6172 -2.72,-4.8359 -4.59,-6.668 -1.88,-1.8281 -4.09,-3.2304 -6.63,-4.2226 -2.56,-0.9844 -5.37,-1.4844 -8.5,-1.4844 -4.15,0 -7.79,0.7617 -10.93,2.2656 -3.13,1.5079 -5.74,3.5196 -7.83,6.0391 -2.05,2.5156 -3.62,5.4297 -4.65,8.7461 -1.04,3.3008 -1.56,6.7812 -1.56,10.4414 0,3.6602 0.52,7.1445 1.56,10.4492 1.03,3.3125 2.6,6.2383 4.65,8.7813 2.09,2.5429 4.7,4.5742 7.83,6.0781 3.14,1.5078 6.78,2.2578 10.93,2.2578 2.52,0 4.97,-0.3711 7.38,-1.1094 2.39,-0.7382 4.57,-1.8398 6.52,-3.2968 1.95,-1.461 3.57,-3.25 4.89,-5.3711 1.31,-2.1289 2.14,-4.5703 2.48,-7.3399 l -5.04,0 c -0.45,2.0274 -1.17,3.8399 -2.17,5.4492"
|
||||||
|
id="path3130"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 2519.59,81.2695 0,-4.2929 -31.5,0 0,-19.1211 29.5,0 0,-4.3008 -29.5,0 0,-20.8945 31.86,0 0,-4.3047 -36.9,0 0,52.914 36.54,0"
|
||||||
|
id="path3132"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 109.109,130.879 c -2.171,6.246 -5.242,11.781 -9.2145,16.601 -3.9765,4.825 -8.8007,8.7 -14.4765,11.637 -5.6758,2.938 -12.1133,4.395 -19.2969,4.395 -7.375,0 -13.9023,-1.457 -19.5781,-4.395 -5.6797,-2.937 -10.5039,-6.812 -14.4766,-11.637 -3.9726,-4.82 -7.1406,-10.41 -9.5078,-16.75 -2.3633,-6.332 -3.9258,-12.816 -4.6758,-19.433 l 94.7732,0 c -0.179,6.812 -1.371,13.348 -3.547,19.582 z M 20.5703,76.2539 c 1.8008,-6.9141 4.6875,-13.1055 8.6563,-18.5937 3.9765,-5.4883 8.9922,-10.0235 15.0429,-13.6133 6.0547,-3.6016 13.336,-5.3985 21.8516,-5.3985 13.0586,0 23.2734,3.4102 30.6484,10.2188 7.3755,6.8008 12.4885,15.8867 15.3205,27.2344 l 17.883,0 C 126.184,59.457 119.234,46.5898 109.109,37.5195 98.9922,28.4258 84.6602,23.8906 66.1211,23.8906 c -11.5352,0 -21.5234,2.043 -29.9336,6.1133 C 27.7578,34.0664 20.9023,39.6445 15.6094,46.7422 10.3125,53.8281 6.39063,62.0586 3.83203,71.4336 1.28125,80.7891 0,90.6719 0,101.086 c 0,9.641 1.28125,19.098 3.83203,28.371 2.5586,9.27 6.48047,17.551 11.77737,24.828 5.2929,7.285 12.1484,13.153 20.5781,17.606 8.4102,4.437 18.3984,6.664 29.9336,6.664 11.7266,0 21.7539,-2.375 30.0859,-7.102 8.32,-4.719 15.078,-10.922 20.285,-18.578 5.196,-7.66 8.938,-16.461 11.203,-26.395 2.278,-9.937 3.219,-20 2.84,-30.2222 l -112.6522,0 c 0,-6.4336 0.8867,-13.1055 2.6875,-20.0039"
|
||||||
|
id="path3134"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 157.859,174.297 0,-25.258 0.571,0 c 3.41,8.895 9.457,16.039 18.164,21.426 8.695,5.398 18.254,8.09 28.66,8.09 10.219,0 18.777,-1.325 25.68,-3.977 6.91,-2.648 12.441,-6.379 16.601,-11.203 4.16,-4.824 7.098,-10.738 8.797,-17.734 1.699,-7.008 2.555,-14.864 2.555,-23.555 l 0,-94.2188 -17.875,0 0,91.3708 c 0,6.246 -0.567,12.059 -1.703,17.461 -1.141,5.387 -3.121,10.067 -5.957,14.047 -2.844,3.969 -6.676,7.09 -11.5,9.359 -4.821,2.274 -10.829,3.407 -18.02,3.407 -7.191,0 -13.578,-1.278 -19.152,-3.828 -5.578,-2.555 -10.309,-6.055 -14.192,-10.5 -3.879,-4.442 -6.91,-9.743 -9.082,-15.895 -2.172,-6.156 -3.355,-12.82 -3.547,-20.004 l 0,-85.4178 -17.871,0 0,146.4298 17.871,0"
|
||||||
|
id="path3136"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 274.938,174.297 45.976,-128.5509 0.566,0 45.407,128.5509 18.449,0 -54.77,-146.4298 -19.019,0 -56.465,146.4298 19.856,0"
|
||||||
|
id="path3138"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 409.707,174.297 0,-146.4298 -17.875,0 0,146.4298 17.875,0 z m 0,56.187 0,-28.664 -17.875,0 0,28.664 17.875,0"
|
||||||
|
id="path3140"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 487.02,104.863 c 3.683,0 7.222,0.27 10.632,0.809 3.407,0.547 6.403,1.601 8.993,3.172 2.589,1.566 4.668,3.785 6.238,6.648 1.558,2.852 2.347,6.613 2.347,11.235 0,4.636 -0.789,8.39 -2.347,11.25 -1.57,2.859 -3.649,5.074 -6.238,6.64 -2.59,1.571 -5.586,2.629 -8.993,3.172 -3.41,0.547 -6.949,0.813 -10.632,0.813 l -24.934,0 0,-43.739 24.934,0 z m 8.793,68.68 c 9.128,0 16.898,-1.32 23.304,-3.988 6.406,-2.66 11.613,-6.16 15.633,-10.524 4.023,-4.359 6.961,-9.34 8.797,-14.922 1.84,-5.589 2.758,-11.379 2.758,-17.382 0,-5.852 -0.918,-11.614 -2.758,-17.27 -1.836,-5.652 -4.774,-10.664 -8.797,-15.0273 -4.02,-4.3633 -9.227,-7.8672 -15.633,-10.5234 -6.406,-2.6602 -14.176,-3.9844 -23.304,-3.9844 l -33.727,0 0,-52.336 -32.102,0 0,145.9571 65.829,0"
|
||||||
|
id="path3142"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 614.273,76.7539 c -1.835,-0.6211 -3.812,-1.1289 -5.929,-1.5351 -2.114,-0.4102 -4.324,-0.75 -6.641,-1.0196 -2.316,-0.2773 -4.637,-0.6211 -6.953,-1.0273 -2.176,-0.4102 -4.328,-0.9571 -6.437,-1.6328 -2.114,-0.6836 -3.958,-1.6016 -5.52,-2.7618 -1.566,-1.1562 -2.832,-2.625 -3.777,-4.3945 -0.957,-1.7773 -1.438,-4.0234 -1.438,-6.7461 0,-2.5937 0.481,-4.7695 1.438,-6.5429 0.945,-1.7696 2.246,-3.168 3.879,-4.1915 1.636,-1.0234 3.543,-1.7382 5.726,-2.1484 2.176,-0.4101 4.426,-0.6094 6.746,-0.6094 5.723,0 10.145,0.9532 13.285,2.8672 3.133,1.9024 5.45,4.1875 6.953,6.8438 1.497,2.6562 2.418,5.3476 2.758,8.0742 0.336,2.7226 0.516,4.9101 0.516,6.543 l 0,10.8398 c -1.234,-1.1055 -2.766,-1.9492 -4.606,-2.5586 z m -57.339,40.9841 c 3,4.496 6.812,8.106 11.449,10.832 4.637,2.723 9.844,4.672 15.637,5.828 5.789,1.157 11.617,1.735 17.48,1.735 5.316,0 10.691,-0.375 16.145,-1.125 5.457,-0.75 10.425,-2.211 14.921,-4.395 4.504,-2.175 8.18,-5.207 11.043,-9.093 2.86,-3.883 4.297,-9.032 4.297,-15.434 l 0,-54.9922 c 0,-4.7774 0.27,-9.336 0.817,-13.6954 0.539,-4.3632 1.496,-7.6328 2.859,-9.8125 l -29.437,0 c -0.543,1.6329 -0.989,3.3008 -1.329,5.0118 -0.343,1.6992 -0.582,3.4414 -0.718,5.2109 -4.633,-4.7734 -10.082,-8.1133 -16.348,-10.0156 -6.273,-1.9063 -12.676,-2.8672 -19.219,-2.8672 -5.043,0 -9.746,0.6172 -14.105,1.8398 -4.367,1.2266 -8.18,3.1367 -11.449,5.7305 -3.27,2.5859 -5.825,5.8594 -7.668,9.8125 -1.84,3.9492 -2.758,8.6523 -2.758,14.1016 0,5.9961 1.058,10.9375 3.168,14.8242 2.109,3.8789 4.836,6.9726 8.179,9.2969 3.34,2.3164 7.157,4.0585 11.446,5.2148 4.297,1.1562 8.617,2.0742 12.98,2.7539 4.364,0.6836 8.656,1.2266 12.879,1.6367 4.227,0.4102 7.973,1.0235 11.25,1.8438 3.266,0.8125 5.856,2.0117 7.762,3.582 1.91,1.5664 2.793,3.8477 2.664,6.8435 0,3.137 -0.516,5.617 -1.535,7.461 -1.028,1.844 -2.395,3.266 -4.09,4.293 -1.707,1.02 -3.68,1.699 -5.93,2.039 -2.25,0.344 -4.672,0.516 -7.258,0.516 -5.718,0 -10.222,-1.223 -13.488,-3.68 -3.277,-2.453 -5.183,-6.543 -5.726,-12.265 l -29.032,0 c 0.41,6.816 2.118,12.46 5.114,16.968"
|
||||||
|
id="path3144"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 720.172,133.277 0,-19.422 -21.254,0 0,-52.3355 c 0,-4.9023 0.812,-8.1718 2.449,-9.8047 1.637,-1.6406 4.903,-2.4609 9.817,-2.4609 1.632,0 3.195,0.0703 4.699,0.2031 1.496,0.1328 2.926,0.3438 4.289,0.6172 l 0,-22.4883 c -2.453,-0.414 -5.176,-0.6836 -8.176,-0.8203 -2.996,-0.1289 -5.926,-0.1992 -8.789,-0.1992 -4.5,0 -8.754,0.3047 -12.773,0.918 -4.024,0.6094 -7.563,1.8086 -10.629,3.5781 -3.071,1.7695 -5.489,4.293 -7.254,7.5586 -1.781,3.2773 -2.664,7.5703 -2.664,12.8828 l 0,62.3511 -17.578,0 0,19.422 17.578,0 0,31.684 29.031,0 0,-31.684 21.254,0"
|
||||||
|
id="path3146"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 755.918,173.543 0,-54.984 0.613,0 c 3.684,6.125 8.387,10.586 14.11,13.379 5.722,2.796 11.312,4.195 16.761,4.195 7.77,0 14.137,-1.059 19.114,-3.164 4.972,-2.114 8.894,-5.043 11.754,-8.793 2.863,-3.75 4.871,-8.317 6.031,-13.699 1.152,-5.383 1.734,-11.3481 1.734,-17.8832 l 0,-65.0079 -29.027,0 0,59.6954 c 0,8.7148 -1.363,15.2227 -4.086,19.5157 -2.731,4.293 -7.567,6.433 -14.516,6.433 -7.902,0 -13.633,-2.343 -17.172,-7.039 -3.543,-4.703 -5.316,-12.441 -5.316,-23.2144 l 0,-55.3907 -29.023,0 0,145.9571 29.023,0"
|
||||||
|
id="path3148"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 863.082,0 21.875,0 0,190.547 -21.875,0 0,-190.547 z"
|
||||||
|
id="path3150"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 41 KiB |
59
static/images/logo-short-white.svg
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
version="1.1"
|
||||||
|
width="103.4625"
|
||||||
|
height="25.825001"
|
||||||
|
id="svg3227"
|
||||||
|
xml:space="preserve"><metadata
|
||||||
|
id="metadata3233"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs3231"><filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter3283"><feColorMatrix
|
||||||
|
id="feColorMatrix3285"
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate" /><feColorMatrix
|
||||||
|
id="feColorMatrix3287"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
|
||||||
|
in="fbSourceGraphic" /></filter></defs><g
|
||||||
|
transform="matrix(1.25,0,0,-1.25,0,25.825)"
|
||||||
|
id="g3235"><g
|
||||||
|
transform="scale(0.1,0.1)"
|
||||||
|
id="g3237"
|
||||||
|
style="filter:url(#filter3283)"><path
|
||||||
|
d="m 109.105,106.992 c -2.167,6.25 -5.234,11.797 -9.2183,16.602 -3.9648,4.824 -8.789,8.711 -14.4726,11.64 -5.6719,2.95 -12.1094,4.395 -19.2969,4.395 -7.3711,0 -13.9063,-1.445 -19.5703,-4.395 -5.6836,-2.929 -10.5078,-6.816 -14.4805,-11.64 -3.9766,-4.805 -7.1406,-10.41 -9.5039,-16.739 -2.3633,-6.328 -3.9258,-12.812 -4.6875,-19.4331 l 94.785,0 c -0.183,6.8164 -1.375,13.3401 -3.555,19.5701 z M 20.5703,52.3828 c 1.7969,-6.914 4.6875,-13.1055 8.6524,-18.5937 3.9843,-5.4883 8.9961,-10.0391 15.039,-13.6133 6.0547,-3.6133 13.3399,-5.4102 21.8555,-5.4102 13.0664,0 23.2812,3.418 30.6445,10.2149 7.3833,6.8164 12.5003,15.8984 15.3323,27.2461 l 17.871,0 C 126.176,35.5859 119.234,22.7148 109.105,13.6328 98.9883,4.55078 84.6523,0.0195313 66.1172,0.0195313 54.5859,0.0195313 44.5938,2.05078 36.1875,6.13281 27.7578,10.1953 20.9023,15.7617 15.6094,22.8711 10.3164,29.9414 6.39063,38.1836 3.83203,47.5586 1.27344,56.9141 0.00390625,66.7969 0.00390625,77.207 c 0,9.6485 1.26953375,19.1016 3.82812375,28.379 2.5586,9.258 6.48437,17.539 11.77737,24.824 5.2929,7.285 12.1484,13.145 20.5781,17.598 8.4063,4.433 18.3984,6.66 29.9297,6.66 11.7305,0 21.7578,-2.363 30.0898,-7.09 8.32,-4.726 15.078,-10.918 20.281,-18.574 5.196,-7.676 8.946,-16.465 11.211,-26.406 2.266,-9.9417 3.215,-20.0003 2.832,-30.2152 l -112.656,0 c 0,-6.4453 0.8984,-13.1055 2.6953,-20"
|
||||||
|
id="path3239"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 157.855,150.41 0,-25.254 0.567,0 c 3.418,8.907 9.465,16.035 18.164,21.426 8.703,5.41 18.262,8.086 28.672,8.086 10.215,0 18.769,-1.309 25.676,-3.965 6.902,-2.656 12.441,-6.387 16.601,-11.211 4.16,-4.824 7.098,-10.742 8.797,-17.734 1.699,-7.012 2.559,-14.863 2.559,-23.5549 l 0,-94.21872 -17.879,0 0,91.36722 c 0,6.2504 -0.567,12.0704 -1.711,17.4614 -1.133,5.39 -3.113,10.078 -5.957,14.062 -2.832,3.965 -6.668,7.09 -11.492,9.355 -4.817,2.266 -10.832,3.399 -18.02,3.399 -7.187,0 -13.574,-1.27 -19.16,-3.828 -5.567,-2.559 -10.301,-6.055 -14.18,-10.488 -3.887,-4.454 -6.914,-9.747 -9.082,-15.899 -2.176,-6.152 -3.359,-12.832 -3.555,-19.9999 l 0,-85.42972 -17.871,0 0,146.42562 17.871,0"
|
||||||
|
id="path3241"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 274.938,150.41 45.976,-128.535 0.566,0 45.399,128.535 18.457,0 -54.766,-146.42562 -19.023,0 -56.465,146.42562 19.856,0"
|
||||||
|
id="path3243"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 409.711,150.41 0,-146.42562 -17.879,0 0,146.42562 17.879,0 z m 0,56.192 0,-28.653 -17.879,0 0,28.653 17.879,0"
|
||||||
|
id="path3245"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 488.297,80.9766 c 3.68,0 7.215,0.2734 10.633,0.8203 3.398,0.5469 6.398,1.6015 8.984,3.164 2.598,1.5625 4.668,3.7891 6.242,6.6602 1.563,2.8516 2.352,6.6016 2.352,11.2309 0,4.628 -0.789,8.378 -2.352,11.25 -1.574,2.851 -3.644,5.078 -6.242,6.64 -2.586,1.563 -5.586,2.617 -8.984,3.164 -3.418,0.547 -6.953,0.821 -10.633,0.821 l -24.934,0 0,-43.7504 24.934,0 z m 8.789,68.6914 c 9.129,0 16.902,-1.328 23.309,-3.984 6.406,-2.676 11.613,-6.172 15.625,-10.528 4.023,-4.355 6.964,-9.336 8.8,-14.922 1.844,-5.586 2.762,-11.386 2.762,-17.382 0,-5.8598 -0.918,-11.6215 -2.762,-17.2661 -1.836,-5.664 -4.777,-10.664 -8.8,-15.039 -4.012,-4.3555 -9.219,-7.8711 -15.625,-10.5274 -6.407,-2.6562 -14.18,-3.9843 -23.309,-3.9843 l -33.723,0 0,-52.32426 -32.109,0 0,145.95706 65.832,0"
|
||||||
|
id="path3247"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 615.551,52.8711 c -1.836,-0.625 -3.817,-1.1328 -5.938,-1.5234 -2.109,-0.4102 -4.316,-0.7618 -6.64,-1.0352 -2.313,-0.2734 -4.629,-0.6055 -6.953,-1.0156 -2.168,-0.4102 -4.325,-0.9571 -6.434,-1.6406 -2.109,-0.6836 -3.957,-1.6016 -5.52,-2.754 -1.562,-1.1523 -2.832,-2.6367 -3.777,-4.3945 -0.957,-1.7773 -1.437,-4.0234 -1.437,-6.7578 0,-2.5781 0.48,-4.7656 1.437,-6.543 0.945,-1.7578 2.246,-3.164 3.875,-4.1797 1.641,-1.0351 3.547,-1.7382 5.734,-2.1484 2.176,-0.4101 4.422,-0.6055 6.747,-0.6055 5.722,0 10.136,0.9375 13.281,2.8516 3.137,1.9141 5.449,4.1992 6.953,6.8555 1.496,2.6562 2.422,5.3515 2.754,8.0664 0.344,2.7344 0.519,4.9219 0.519,6.5429 l 0,10.8399 c -1.23,-1.0938 -2.765,-1.9531 -4.601,-2.5586 z m -57.344,40.9961 c 3,4.4922 6.816,8.1058 11.445,10.8208 4.641,2.734 9.844,4.667 15.645,5.839 5.781,1.153 11.613,1.719 17.48,1.719 5.313,0 10.684,-0.371 16.145,-1.113 5.457,-0.762 10.418,-2.207 14.922,-4.395 4.5,-2.187 8.172,-5.215 11.043,-9.1013 2.851,-3.8867 4.297,-9.0234 4.297,-15.4297 l 0,-55 c 0,-4.7656 0.265,-9.3359 0.812,-13.6914 0.535,-4.35544 1.492,-7.63669 2.859,-9.80466 l -29.433,0 c -0.547,1.62109 -0.996,3.30078 -1.328,5 -0.352,1.69926 -0.586,3.45706 -0.723,5.21486 C 616.742,9.16016 611.293,5.82031 605.023,3.90625 598.754,2.01172 592.348,1.05469 585.805,1.05469 c -5.039,0 -9.746,0.60547 -14.102,1.83594 -4.375,1.23046 -8.183,3.125 -11.453,5.72265 -3.273,2.59762 -5.82,5.85942 -7.668,9.82422 -1.836,3.9453 -2.754,8.6523 -2.754,14.1016 0,5.9961 1.055,10.9375 3.164,14.8242 2.11,3.8672 4.836,6.9726 8.184,9.2969 3.34,2.3046 7.148,4.0429 11.445,5.2148 4.297,1.1523 8.613,2.0703 12.981,2.7539 4.363,0.6836 8.652,1.2109 12.878,1.6211 4.219,0.4102 7.969,1.0352 11.25,1.8555 3.262,0.8008 5.852,2.0117 7.754,3.5742 1.914,1.5625 2.793,3.8476 2.668,6.8555 0,3.125 -0.519,5.6054 -1.535,7.4609 -1.023,1.8359 -2.39,3.2617 -4.09,4.2773 -1.711,1.0352 -3.683,1.6993 -5.929,2.0508 -2.246,0.3321 -4.668,0.5078 -7.254,0.5078 -5.723,0 -10.227,-1.2109 -13.489,-3.6718 -3.281,-2.461 -5.183,-6.543 -5.73,-12.2657 l -29.035,0 c 0.41,6.8164 2.121,12.461 5.117,16.9727"
|
||||||
|
id="path3249"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 721.449,109.395 0,-19.4145 -21.258,0 0,-52.3438 c 0,-4.9023 0.809,-8.164 2.45,-9.8047 1.64,-1.6406 4.902,-2.4609 9.816,-2.4609 1.629,0 3.191,0.0781 4.695,0.2148 1.504,0.1172 2.93,0.3321 4.297,0.6055 l 0,-22.48046 c -2.461,-0.41016 -5.176,-0.6836 -8.183,-0.82031 -2.989,-0.13672 -5.918,-0.19532 -8.789,-0.19532 -4.493,0 -8.75,0.29297 -12.774,0.91797 -4.023,0.60547 -7.558,1.79688 -10.625,3.57422 -3.066,1.75781 -5.488,4.2969 -7.254,7.5586 -1.777,3.2812 -2.668,7.5586 -2.668,12.8711 l 0,62.3633 -17.578,0 0,19.4145 17.578,0 0,31.679 29.035,0 0,-31.679 21.258,0"
|
||||||
|
id="path3251"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
||||||
|
d="m 757.621,149.668 0,-54.9805 0.606,0 c 3.691,6.1135 8.39,10.5855 14.113,13.3785 5.723,2.793 11.316,4.18 16.765,4.18 7.766,0 14.133,-1.055 19.102,-3.164 4.981,-2.109 8.906,-5.039 11.758,-8.789 2.871,-3.75 4.875,-8.3203 6.035,-13.6914 1.152,-5.3907 1.738,-11.3477 1.738,-17.8907 l 0,-64.99996 -29.031,0 0,59.68746 c 0,8.711 -1.359,15.2344 -4.094,19.5118 -2.722,4.2968 -7.558,6.4453 -14.511,6.4453 -7.899,0 -13.633,-2.3438 -17.168,-7.0508 -3.543,-4.6875 -5.313,-12.4414 -5.313,-23.2031 l 0,-55.39066 -29.023,0 0,145.95706 29.023,0"
|
||||||
|
id="path3253"
|
||||||
|
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 8.2 KiB |
BIN
static/images/uoa.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
488
static/images/uzh-logo.svg
Normal file
@ -0,0 +1,488 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
|
||||||
|
<svg version="1.1" baseProfile="tiny" id="Universität_Zürich"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="-0.499 -0.501 142.73 49.19" xml:space="preserve">
|
||||||
|
<path d="M6.818,32.721C6.296,32.944,6.2,32.986,6.093,33.04c-0.113,0.058-0.156,0.108-0.133,0.231
|
||||||
|
c0.005,0.029,0.026,0.091,0.047,0.139c0.017,0.038,0.019,0.062-0.006,0.071c-0.023,0.011-0.041-0.01-0.062-0.062
|
||||||
|
c-0.078-0.182-0.161-0.401-0.205-0.506c-0.035-0.082-0.138-0.295-0.191-0.418c-0.021-0.052-0.024-0.079-0.001-0.089
|
||||||
|
c0.024-0.011,0.04,0.007,0.056,0.042c0.016,0.037,0.027,0.057,0.053,0.095c0.057,0.086,0.127,0.088,0.25,0.043
|
||||||
|
c0.113-0.04,0.209-0.081,0.731-0.305l0.481-0.206c0.499-0.215,0.666-0.404,0.729-0.631c0.062-0.21,0.008-0.373-0.043-0.49
|
||||||
|
c-0.063-0.151-0.191-0.315-0.389-0.395c-0.27-0.108-0.584,0.014-0.938,0.166l-0.431,0.184c-0.521,0.225-0.619,0.266-0.726,0.319
|
||||||
|
c-0.114,0.058-0.157,0.107-0.132,0.23c0.005,0.031,0.025,0.091,0.042,0.129c0.016,0.037,0.018,0.062-0.006,0.071
|
||||||
|
c-0.024,0.011-0.041-0.011-0.062-0.06C5.083,31.425,5.001,31.204,5,31.201c-0.018-0.042-0.121-0.254-0.178-0.387
|
||||||
|
c-0.021-0.048-0.024-0.075,0-0.085c0.024-0.012,0.04,0.007,0.057,0.048c0.017,0.038,0.029,0.058,0.054,0.096
|
||||||
|
c0.057,0.085,0.127,0.088,0.25,0.043c0.112-0.04,0.209-0.082,0.73-0.306l0.368-0.157c0.382-0.164,0.803-0.3,1.175-0.117
|
||||||
|
c0.314,0.154,0.458,0.387,0.554,0.608c0.078,0.183,0.21,0.517,0.091,0.865c-0.083,0.242-0.281,0.481-0.78,0.695L6.818,32.721z
|
||||||
|
M6.676,28.899c0.283-0.069,0.368-0.139,0.378-0.217c0.008-0.066-0.004-0.138-0.017-0.195c-0.009-0.04-0.007-0.063,0.017-0.068
|
||||||
|
c0.028-0.006,0.043,0.025,0.055,0.076c0.052,0.237,0.073,0.386,0.088,0.455c0.007,0.033,0.056,0.202,0.098,0.393
|
||||||
|
c0.011,0.048,0.015,0.081-0.019,0.089c-0.022,0.005-0.034-0.017-0.042-0.053c-0.01-0.048-0.028-0.111-0.054-0.16
|
||||||
|
c-0.051-0.089-0.159-0.079-0.479-0.015l-2.169,0.442c-0.073,0.016-0.127,0.016-0.135-0.021c-0.009-0.04,0.031-0.083,0.083-0.16
|
||||||
|
c0.038-0.054,0.511-0.739,0.924-1.39c0.194-0.303,0.612-0.911,0.657-0.986l-0.004-0.018l-1.633,0.396
|
||||||
|
c-0.222,0.053-0.283,0.102-0.301,0.196c-0.01,0.061,0.009,0.146,0.021,0.198c0.01,0.044,0.002,0.061-0.021,0.064
|
||||||
|
c-0.028,0.008-0.042-0.032-0.054-0.088C4.028,27.651,4,27.474,3.984,27.397c-0.009-0.041-0.05-0.178-0.09-0.356
|
||||||
|
c-0.011-0.048-0.016-0.085,0.015-0.091c0.022-0.005,0.038,0.015,0.047,0.059c0.008,0.036,0.015,0.065,0.035,0.106
|
||||||
|
c0.051,0.097,0.135,0.108,0.34,0.067l2.313-0.467c0.08-0.018,0.115-0.01,0.124,0.022c0.009,0.041-0.021,0.094-0.054,0.143
|
||||||
|
c-0.168,0.277-0.544,0.852-0.837,1.312c-0.308,0.484-0.675,0.99-0.729,1.071l0.002,0.011L6.676,28.899z M4.871,25.556
|
||||||
|
c-0.566,0.035-0.672,0.042-0.791,0.058c-0.126,0.016-0.188,0.057-0.201,0.14C3.87,25.796,3.87,25.844,3.873,25.89
|
||||||
|
c0.002,0.036-0.004,0.06-0.034,0.062c-0.021,0.002-0.031-0.027-0.035-0.087c-0.01-0.142-0.014-0.378-0.021-0.486
|
||||||
|
c-0.006-0.093-0.031-0.312-0.04-0.455c-0.003-0.048,0.003-0.079,0.025-0.081c0.029-0.002,0.039,0.021,0.041,0.059
|
||||||
|
c0.002,0.037,0.008,0.066,0.018,0.111c0.025,0.1,0.09,0.126,0.222,0.123c0.12,0,0.225-0.006,0.792-0.042l0.657-0.042
|
||||||
|
c0.362-0.021,0.657-0.041,0.816-0.065c0.1-0.019,0.166-0.048,0.173-0.161c0.004-0.053,0.006-0.135,0.003-0.191
|
||||||
|
c-0.002-0.042,0.007-0.061,0.026-0.062c0.025-0.001,0.039,0.028,0.042,0.069c0.016,0.246,0.02,0.48,0.025,0.583
|
||||||
|
c0.005,0.086,0.031,0.319,0.041,0.47c0.003,0.048-0.006,0.075-0.033,0.076c-0.019,0.002-0.03-0.014-0.033-0.059
|
||||||
|
c-0.003-0.056-0.015-0.1-0.023-0.133c-0.02-0.074-0.084-0.093-0.193-0.097c-0.157-0.009-0.452,0.01-0.814,0.032L4.871,25.556z
|
||||||
|
M4.071,23.877c-0.21,0.073-0.256,0.134-0.302,0.267c-0.02,0.055-0.022,0.114-0.024,0.145c-0.002,0.034-0.014,0.044-0.037,0.043
|
||||||
|
c-0.029-0.002-0.031-0.043-0.026-0.099c0.013-0.198,0.038-0.41,0.045-0.541c0.006-0.093,0.006-0.273,0.019-0.46
|
||||||
|
c0.003-0.045,0.013-0.085,0.039-0.084c0.026,0.002,0.032,0.024,0.03,0.059c-0.003,0.061-0.003,0.116,0.017,0.147
|
||||||
|
c0.018,0.026,0.042,0.041,0.076,0.042c0.049,0.003,0.155-0.024,0.293-0.067l1.736-0.534l0.001-0.015
|
||||||
|
c-0.4-0.188-1.571-0.749-1.812-0.854c-0.047-0.021-0.102-0.041-0.136-0.042c-0.03-0.002-0.061,0.012-0.074,0.044
|
||||||
|
c-0.018,0.045-0.024,0.101-0.027,0.148c-0.003,0.034-0.009,0.063-0.034,0.062c-0.03-0.002-0.035-0.036-0.031-0.106
|
||||||
|
c0.012-0.188,0.033-0.343,0.036-0.391c0.004-0.063,0.004-0.24,0.011-0.353c0.003-0.048,0.013-0.078,0.039-0.076
|
||||||
|
c0.026,0.001,0.032,0.024,0.029,0.062C3.935,21.311,3.93,21.389,3.97,21.46C4,21.51,4.06,21.571,4.293,21.687
|
||||||
|
c0.342,0.168,0.537,0.281,0.983,0.513c0.53,0.274,0.926,0.476,1.106,0.569c0.21,0.11,0.27,0.137,0.266,0.188
|
||||||
|
c-0.003,0.048-0.058,0.067-0.236,0.127L4.071,23.877z M5.128,20.567c-0.556-0.12-0.657-0.143-0.776-0.16
|
||||||
|
c-0.126-0.019-0.191-0.002-0.242,0.113c-0.014,0.026-0.031,0.089-0.042,0.14c-0.009,0.041-0.021,0.062-0.046,0.055
|
||||||
|
c-0.026-0.006-0.027-0.032-0.017-0.087c0.021-0.099,0.047-0.204,0.067-0.295c0.024-0.095,0.045-0.178,0.057-0.229
|
||||||
|
c0.025-0.117,0.183-0.846,0.193-0.916c0.007-0.071,0.013-0.131,0.012-0.162c0-0.02-0.006-0.043-0.002-0.062
|
||||||
|
c0.004-0.018,0.02-0.019,0.038-0.015c0.025,0.005,0.065,0.033,0.231,0.08c0.036,0.012,0.194,0.054,0.236,0.07
|
||||||
|
c0.019,0.008,0.038,0.02,0.032,0.045c-0.005,0.024-0.024,0.028-0.058,0.021C4.787,19.16,4.724,19.15,4.676,19.16
|
||||||
|
c-0.07,0.011-0.122,0.039-0.185,0.216c-0.021,0.062-0.11,0.443-0.126,0.518c-0.004,0.019,0.005,0.027,0.031,0.032l0.925,0.199
|
||||||
|
c0.025,0.005,0.041,0.005,0.045-0.017c0.018-0.081,0.108-0.501,0.119-0.587c0.011-0.089,0.012-0.146-0.018-0.188
|
||||||
|
c-0.023-0.032-0.038-0.051-0.034-0.068c0.003-0.016,0.013-0.024,0.034-0.021c0.022,0.005,0.078,0.032,0.262,0.087
|
||||||
|
c0.072,0.02,0.216,0.062,0.242,0.067C6,19.405,6.04,19.414,6.033,19.447c-0.005,0.026-0.021,0.03-0.04,0.026
|
||||||
|
c-0.037-0.005-0.084-0.015-0.135-0.014c-0.077,0.002-0.144,0.042-0.188,0.174c-0.021,0.068-0.104,0.43-0.123,0.518
|
||||||
|
c-0.004,0.018,0.011,0.024,0.032,0.03l0.289,0.062c0.125,0.027,0.46,0.104,0.567,0.122c0.254,0.047,0.32,0,0.401-0.373
|
||||||
|
c0.021-0.095,0.054-0.249,0.03-0.353c-0.022-0.104-0.091-0.165-0.235-0.224C6.594,19.4,6.581,19.39,6.587,19.364
|
||||||
|
c0.008-0.029,0.036-0.023,0.072-0.015c0.084,0.018,0.327,0.101,0.396,0.135c0.089,0.046,0.083,0.079,0.052,0.218
|
||||||
|
c-0.06,0.274-0.109,0.474-0.146,0.63c-0.041,0.156-0.068,0.27-0.093,0.378c-0.009,0.04-0.026,0.121-0.041,0.209
|
||||||
|
C6.808,21.003,6.796,21.1,6.78,21.173c-0.01,0.049-0.026,0.071-0.052,0.065c-0.019-0.004-0.026-0.021-0.018-0.065
|
||||||
|
c0.013-0.055,0.015-0.1,0.015-0.135c0.001-0.076-0.075-0.112-0.179-0.148c-0.149-0.052-0.438-0.113-0.774-0.187L5.128,20.567z
|
||||||
|
M5.822,17.875c-0.53-0.205-0.628-0.243-0.743-0.278c-0.121-0.039-0.188-0.032-0.257,0.072c-0.018,0.025-0.044,0.083-0.063,0.132
|
||||||
|
c-0.015,0.038-0.029,0.058-0.054,0.048c-0.023-0.01-0.021-0.037-0.002-0.09c0.072-0.185,0.167-0.399,0.195-0.474
|
||||||
|
c0.046-0.118,0.138-0.388,0.18-0.496c0.085-0.22,0.196-0.446,0.398-0.584c0.104-0.072,0.336-0.143,0.569-0.052
|
||||||
|
c0.259,0.1,0.454,0.299,0.604,0.763c0.511-0.16,0.915-0.28,1.21-0.401c0.278-0.117,0.357-0.251,0.389-0.3
|
||||||
|
c0.021-0.035,0.038-0.065,0.048-0.094c0.011-0.028,0.026-0.038,0.044-0.031c0.028,0.012,0.025,0.038,0.01,0.08l-0.128,0.332
|
||||||
|
c-0.075,0.195-0.126,0.276-0.21,0.349c-0.139,0.118-0.354,0.188-0.698,0.279c-0.246,0.065-0.545,0.135-0.615,0.159
|
||||||
|
c-0.027,0.009-0.039,0.029-0.048,0.053l-0.125,0.302c-0.007,0.018-0.004,0.03,0.017,0.039l0.049,0.019
|
||||||
|
c0.325,0.125,0.601,0.232,0.754,0.271C7.45,18,7.535,18.009,7.59,17.91c0.027-0.05,0.064-0.124,0.08-0.166
|
||||||
|
c0.012-0.028,0.027-0.038,0.044-0.031c0.024,0.011,0.025,0.038,0.009,0.083c-0.079,0.202-0.188,0.457-0.209,0.51
|
||||||
|
c-0.025,0.065-0.101,0.289-0.154,0.43C7.341,18.779,7.321,18.8,7.297,18.79c-0.018-0.007-0.021-0.023-0.006-0.065
|
||||||
|
c0.021-0.054,0.029-0.098,0.035-0.132c0.013-0.074-0.057-0.123-0.153-0.176c-0.14-0.074-0.415-0.181-0.735-0.305L5.822,17.875z
|
||||||
|
M6.257,17.57c0.038,0.015,0.056,0.013,0.075-0.007c0.053-0.063,0.104-0.164,0.138-0.251c0.054-0.141,0.058-0.19,0.036-0.271
|
||||||
|
c-0.035-0.134-0.157-0.298-0.443-0.408c-0.495-0.191-0.766,0.081-0.846,0.287c-0.033,0.087-0.055,0.151-0.058,0.19
|
||||||
|
c-0.002,0.027,0.009,0.04,0.037,0.05L6.257,17.57z M8.459,16.014c-0.053,0.038-0.074,0.04-0.146-0.001
|
||||||
|
c-0.18-0.103-0.367-0.227-0.417-0.259c-0.047-0.03-0.077-0.061-0.062-0.087c0.018-0.028,0.048-0.016,0.074-0.001
|
||||||
|
c0.042,0.024,0.118,0.05,0.183,0.064c0.281,0.064,0.479-0.077,0.594-0.278c0.166-0.293,0.049-0.549-0.123-0.646
|
||||||
|
C8.4,14.716,8.223,14.68,7.858,14.83l-0.202,0.083c-0.483,0.199-0.781,0.193-1.044,0.044c-0.357-0.204-0.445-0.647-0.188-1.101
|
||||||
|
c0.12-0.212,0.23-0.33,0.302-0.401c0.022-0.024,0.042-0.036,0.064-0.022c0.042,0.023,0.129,0.091,0.383,0.233
|
||||||
|
c0.072,0.041,0.093,0.065,0.078,0.091c-0.013,0.023-0.038,0.021-0.077,0c-0.028-0.017-0.139-0.058-0.263-0.038
|
||||||
|
c-0.089,0.015-0.241,0.054-0.361,0.265C6.413,14.224,6.47,14.45,6.665,14.56c0.15,0.085,0.307,0.074,0.664-0.079l0.12-0.052
|
||||||
|
c0.521-0.227,0.823-0.238,1.133-0.062c0.188,0.107,0.372,0.306,0.393,0.627c0.012,0.222-0.062,0.421-0.16,0.593
|
||||||
|
C8.706,15.776,8.6,15.909,8.459,16.014z M8.373,12.925c-0.459-0.335-0.544-0.396-0.645-0.462c-0.107-0.067-0.182-0.075-0.244-0.021
|
||||||
|
c-0.034,0.026-0.065,0.063-0.091,0.1c-0.022,0.03-0.042,0.044-0.066,0.026c-0.018-0.013-0.006-0.042,0.029-0.09
|
||||||
|
c0.084-0.115,0.231-0.299,0.296-0.387c0.055-0.075,0.176-0.26,0.26-0.375c0.029-0.039,0.052-0.059,0.07-0.046
|
||||||
|
c0.023,0.019,0.017,0.041-0.005,0.071c-0.022,0.03-0.037,0.057-0.058,0.097c-0.044,0.094-0.011,0.154,0.092,0.237
|
||||||
|
c0.092,0.077,0.177,0.139,0.636,0.474l0.532,0.389c0.293,0.214,0.531,0.388,0.671,0.471c0.088,0.05,0.157,0.069,0.235-0.013
|
||||||
|
c0.037-0.038,0.093-0.101,0.125-0.146c0.024-0.033,0.044-0.042,0.061-0.031c0.021,0.017,0.012,0.047-0.013,0.08
|
||||||
|
c-0.146,0.199-0.294,0.384-0.354,0.466c-0.051,0.068-0.18,0.267-0.269,0.387c-0.029,0.04-0.054,0.054-0.074,0.039
|
||||||
|
c-0.016-0.011-0.017-0.03,0.011-0.066c0.033-0.045,0.053-0.086,0.067-0.118c0.031-0.068-0.007-0.125-0.087-0.197
|
||||||
|
c-0.116-0.108-0.354-0.282-0.648-0.496L8.373,12.925z M9.295,10.406l-0.372,0.415c-0.144,0.163-0.19,0.241-0.17,0.338
|
||||||
|
c0.016,0.065,0.035,0.11,0.052,0.136c0.017,0.026,0.02,0.044,0.004,0.062c-0.019,0.019-0.037,0.012-0.066-0.018
|
||||||
|
c-0.044-0.041-0.242-0.326-0.259-0.353c-0.028-0.042-0.036-0.065-0.021-0.081c0.021-0.022,0.073-0.023,0.144-0.086
|
||||||
|
c0.083-0.071,0.186-0.169,0.271-0.259l1.018-1.076c0.083-0.087,0.131-0.154,0.164-0.2c0.029-0.049,0.045-0.076,0.056-0.086
|
||||||
|
c0.018-0.019,0.037-0.006,0.078,0.032c0.057,0.054,0.237,0.238,0.308,0.306c0.024,0.028,0.036,0.049,0.021,0.065
|
||||||
|
c-0.021,0.021-0.039,0.014-0.083-0.021l-0.032-0.024c-0.076-0.062-0.221-0.061-0.456,0.177l-0.332,0.335l1.115,1.053
|
||||||
|
c0.25,0.236,0.465,0.439,0.595,0.536c0.083,0.062,0.159,0.104,0.247,0.032c0.042-0.033,0.104-0.087,0.142-0.128
|
||||||
|
c0.028-0.03,0.05-0.036,0.062-0.023c0.02,0.019,0.007,0.047-0.021,0.077c-0.169,0.18-0.339,0.343-0.41,0.419
|
||||||
|
c-0.06,0.062-0.214,0.242-0.315,0.351c-0.033,0.035-0.06,0.047-0.079,0.028c-0.014-0.013-0.012-0.031,0.02-0.063
|
||||||
|
c0.038-0.041,0.063-0.078,0.081-0.108c0.04-0.065-0.004-0.138-0.074-0.22c-0.103-0.122-0.316-0.324-0.566-0.562L9.295,10.406z
|
||||||
|
M12.134,9.947c-0.015,0.012-0.016,0.021-0.008,0.044l0.176,0.544c0.029,0.096,0.07,0.178,0.099,0.213
|
||||||
|
c0.042,0.053,0.099,0.069,0.188-0.003l0.044-0.035c0.035-0.027,0.049-0.028,0.062-0.012c0.019,0.023,0.006,0.043-0.026,0.069
|
||||||
|
c-0.094,0.074-0.227,0.166-0.316,0.237c-0.032,0.026-0.187,0.163-0.338,0.284c-0.038,0.03-0.061,0.039-0.079,0.016
|
||||||
|
c-0.015-0.019-0.007-0.033,0.017-0.052c0.026-0.021,0.065-0.057,0.086-0.078c0.121-0.125,0.097-0.269,0.039-0.461l-0.73-2.421
|
||||||
|
c-0.032-0.112-0.041-0.159-0.012-0.182c0.026-0.021,0.065-0.009,0.147,0.035c0.199,0.104,1.618,0.924,2.159,1.22
|
||||||
|
c0.32,0.174,0.438,0.148,0.512,0.113c0.051-0.026,0.097-0.059,0.132-0.086c0.023-0.02,0.041-0.027,0.057-0.008
|
||||||
|
c0.02,0.023-0.003,0.051-0.11,0.138c-0.105,0.084-0.319,0.254-0.558,0.435c-0.055,0.039-0.09,0.067-0.105,0.047
|
||||||
|
c-0.014-0.018-0.007-0.032,0.02-0.059c0.017-0.022,0.016-0.065-0.026-0.088l-0.729-0.434c-0.017-0.01-0.031-0.009-0.045,0.003
|
||||||
|
L12.134,9.947z M12.614,9.325c0.014-0.012,0.01-0.022,0-0.029l-0.839-0.513c-0.012-0.009-0.027-0.021-0.036-0.015
|
||||||
|
c-0.009,0.007-0.003,0.025,0.003,0.041l0.305,0.934c0.008,0.014,0.018,0.021,0.028,0.011L12.614,9.325z M14.557,9.301
|
||||||
|
c-0.064,0.009-0.084-0.002-0.126-0.072c-0.104-0.178-0.206-0.378-0.233-0.432c-0.025-0.05-0.037-0.091-0.011-0.105
|
||||||
|
c0.028-0.018,0.049,0.01,0.063,0.036c0.024,0.042,0.078,0.102,0.126,0.146c0.212,0.196,0.453,0.17,0.652,0.052
|
||||||
|
c0.29-0.172,0.315-0.451,0.214-0.623c-0.093-0.156-0.229-0.276-0.62-0.327l-0.217-0.028c-0.518-0.067-0.773-0.22-0.928-0.48
|
||||||
|
c-0.21-0.354-0.064-0.782,0.383-1.048c0.209-0.124,0.363-0.172,0.46-0.199c0.033-0.011,0.055-0.011,0.068,0.013
|
||||||
|
c0.024,0.042,0.066,0.143,0.216,0.394c0.042,0.071,0.047,0.104,0.021,0.118c-0.021,0.013-0.043,0-0.065-0.039
|
||||||
|
c-0.018-0.029-0.093-0.119-0.209-0.163c-0.084-0.032-0.235-0.074-0.444,0.05c-0.238,0.142-0.301,0.365-0.187,0.559
|
||||||
|
c0.088,0.147,0.229,0.217,0.614,0.261l0.13,0.014c0.562,0.062,0.833,0.202,1.015,0.508c0.109,0.187,0.171,0.45,0.028,0.738
|
||||||
|
c-0.1,0.198-0.263,0.333-0.433,0.436C14.89,9.217,14.731,9.28,14.557,9.301z M34.089,6.584L33.6,6.314
|
||||||
|
c-0.191-0.104-0.278-0.133-0.368-0.09c-0.062,0.028-0.101,0.059-0.121,0.081c-0.022,0.021-0.039,0.028-0.06,0.018
|
||||||
|
c-0.021-0.013-0.02-0.033,0.002-0.069c0.029-0.051,0.264-0.309,0.285-0.332c0.034-0.036,0.056-0.05,0.075-0.038
|
||||||
|
c0.026,0.016,0.039,0.066,0.116,0.12c0.088,0.064,0.207,0.144,0.312,0.205l1.278,0.75c0.104,0.062,0.18,0.093,0.232,0.115
|
||||||
|
c0.054,0.019,0.084,0.027,0.097,0.035c0.022,0.014,0.015,0.035-0.014,0.083c-0.04,0.067-0.181,0.285-0.229,0.369
|
||||||
|
c-0.021,0.03-0.04,0.046-0.06,0.035c-0.025-0.016-0.022-0.035,0.003-0.086l0.018-0.036c0.042-0.089,0.008-0.229-0.274-0.404
|
||||||
|
l-0.401-0.25l-0.776,1.323c-0.174,0.297-0.323,0.552-0.39,0.699c-0.043,0.097-0.064,0.179,0.024,0.248
|
||||||
|
c0.042,0.033,0.108,0.081,0.156,0.109c0.036,0.021,0.047,0.04,0.037,0.056c-0.013,0.022-0.044,0.018-0.08-0.004
|
||||||
|
C33.25,9.129,33.053,9,32.962,8.947c-0.073-0.043-0.282-0.153-0.412-0.229c-0.042-0.023-0.059-0.048-0.046-0.069
|
||||||
|
c0.01-0.017,0.028-0.019,0.067,0.004c0.048,0.029,0.091,0.045,0.124,0.055c0.072,0.025,0.133-0.034,0.197-0.122
|
||||||
|
c0.096-0.126,0.245-0.381,0.42-0.678L34.089,6.584z M35.774,8.711c0.371-0.431,0.438-0.511,0.511-0.605
|
||||||
|
c0.077-0.102,0.093-0.166,0.017-0.267c-0.018-0.024-0.062-0.069-0.104-0.104c-0.031-0.027-0.043-0.047-0.026-0.067
|
||||||
|
c0.018-0.02,0.042-0.009,0.084,0.028c0.15,0.129,0.322,0.291,0.407,0.364c0.068,0.058,0.254,0.204,0.356,0.291
|
||||||
|
c0.042,0.037,0.058,0.059,0.04,0.079c-0.018,0.02-0.039,0.011-0.067-0.014c-0.031-0.026-0.051-0.039-0.09-0.062
|
||||||
|
c-0.089-0.053-0.153-0.022-0.244,0.071c-0.084,0.087-0.152,0.166-0.521,0.598l-0.34,0.396c-0.353,0.412-0.419,0.655-0.378,0.889
|
||||||
|
c0.038,0.214,0.158,0.338,0.255,0.421c0.125,0.106,0.312,0.198,0.523,0.183c0.29-0.021,0.518-0.271,0.769-0.562l0.306-0.354
|
||||||
|
c0.37-0.432,0.438-0.511,0.511-0.605c0.077-0.103,0.093-0.167,0.017-0.268c-0.018-0.024-0.062-0.068-0.095-0.097
|
||||||
|
C37.673,9,37.661,8.979,37.678,8.96c0.017-0.02,0.042-0.009,0.08,0.025c0.146,0.124,0.316,0.286,0.319,0.289
|
||||||
|
c0.034,0.028,0.22,0.174,0.331,0.269c0.04,0.034,0.055,0.058,0.038,0.077c-0.017,0.021-0.039,0.011-0.073-0.018
|
||||||
|
c-0.031-0.027-0.05-0.039-0.089-0.062c-0.089-0.052-0.153-0.022-0.244,0.071c-0.083,0.086-0.151,0.166-0.521,0.597l-0.262,0.303
|
||||||
|
c-0.27,0.315-0.589,0.623-1.002,0.623c-0.35,0-0.581-0.144-0.766-0.302c-0.15-0.129-0.416-0.372-0.462-0.737
|
||||||
|
c-0.033-0.254,0.04-0.557,0.393-0.969L35.774,8.711z M38.61,11.381c0.443-0.355,0.523-0.422,0.613-0.503
|
||||||
|
c0.094-0.085,0.122-0.146,0.064-0.259c-0.013-0.028-0.05-0.08-0.083-0.121c-0.025-0.032-0.034-0.054-0.014-0.071
|
||||||
|
c0.021-0.016,0.043,0,0.078,0.043c0.125,0.154,0.263,0.346,0.312,0.406c0.079,0.1,0.268,0.313,0.339,0.404
|
||||||
|
c0.148,0.184,0.288,0.393,0.308,0.637c0.01,0.126-0.045,0.362-0.24,0.521c-0.216,0.173-0.486,0.242-0.962,0.141
|
||||||
|
c-0.117,0.522-0.215,0.932-0.257,1.249c-0.038,0.299,0.038,0.436,0.063,0.485c0.021,0.037,0.038,0.064,0.058,0.089
|
||||||
|
c0.019,0.022,0.02,0.042,0.005,0.054c-0.023,0.02-0.045,0.003-0.074-0.032l-0.223-0.275c-0.132-0.163-0.176-0.248-0.195-0.356
|
||||||
|
c-0.034-0.179,0.014-0.399,0.106-0.744c0.066-0.246,0.156-0.539,0.171-0.611c0.006-0.029-0.007-0.05-0.022-0.069l-0.198-0.258
|
||||||
|
c-0.012-0.016-0.023-0.02-0.042-0.005l-0.041,0.032c-0.271,0.219-0.501,0.403-0.611,0.517c-0.077,0.077-0.127,0.146-0.068,0.243
|
||||||
|
c0.029,0.048,0.075,0.117,0.103,0.151c0.02,0.023,0.021,0.042,0.006,0.055c-0.021,0.016-0.046,0.003-0.076-0.035
|
||||||
|
c-0.137-0.169-0.301-0.393-0.336-0.437c-0.044-0.055-0.201-0.23-0.294-0.348c-0.031-0.038-0.038-0.065-0.019-0.082
|
||||||
|
c0.016-0.012,0.033-0.007,0.062,0.028c0.034,0.043,0.068,0.073,0.096,0.096c0.059,0.049,0.135,0.012,0.229-0.044
|
||||||
|
c0.135-0.084,0.364-0.271,0.633-0.485L38.61,11.381z M38.656,11.91c-0.032,0.026-0.039,0.041-0.031,0.069
|
||||||
|
c0.029,0.078,0.09,0.172,0.149,0.245c0.094,0.116,0.136,0.145,0.216,0.167c0.134,0.035,0.336,0.013,0.575-0.181
|
||||||
|
c0.414-0.333,0.312-0.703,0.174-0.875c-0.059-0.072-0.104-0.123-0.136-0.145c-0.022-0.017-0.038-0.012-0.062,0.006L38.656,11.91z
|
||||||
|
M40.591,14.113c0.49-0.289,0.58-0.342,0.68-0.409c0.104-0.071,0.142-0.136,0.116-0.216c-0.012-0.041-0.033-0.084-0.056-0.123
|
||||||
|
c-0.02-0.032-0.023-0.056,0.001-0.071c0.021-0.011,0.041,0.012,0.072,0.062c0.072,0.123,0.182,0.331,0.237,0.424
|
||||||
|
c0.047,0.081,0.169,0.265,0.241,0.387c0.024,0.042,0.033,0.072,0.015,0.083c-0.025,0.016-0.043,0-0.062-0.033
|
||||||
|
c-0.019-0.032-0.038-0.056-0.065-0.091c-0.067-0.078-0.139-0.07-0.254-0.011c-0.107,0.054-0.197,0.108-0.688,0.396l-0.566,0.334
|
||||||
|
c-0.312,0.185-0.567,0.335-0.698,0.43c-0.081,0.061-0.126,0.118-0.082,0.222c0.021,0.049,0.056,0.123,0.084,0.172
|
||||||
|
c0.021,0.035,0.021,0.058,0.004,0.066c-0.022,0.014-0.047-0.007-0.068-0.042c-0.125-0.212-0.234-0.421-0.287-0.508
|
||||||
|
c-0.043-0.074-0.173-0.271-0.249-0.4c-0.024-0.042-0.027-0.07-0.006-0.083c0.017-0.009,0.033-0.002,0.057,0.036
|
||||||
|
c0.028,0.049,0.058,0.083,0.082,0.109c0.051,0.057,0.116,0.043,0.216-0.002c0.145-0.063,0.398-0.214,0.712-0.397L40.591,14.113z
|
||||||
|
M40.314,16.493c0.157-0.461,0.507-0.711,0.842-0.85c0.235-0.098,0.672-0.193,1.114,0.013c0.331,0.154,0.604,0.425,0.817,0.94
|
||||||
|
c0.089,0.214,0.128,0.348,0.174,0.515c0.036,0.139,0.052,0.262,0.084,0.37c0.012,0.039,0.001,0.06-0.021,0.068
|
||||||
|
c-0.028,0.012-0.073,0.019-0.197,0.062c-0.116,0.041-0.306,0.123-0.378,0.144c-0.053,0.019-0.084,0.022-0.097-0.008
|
||||||
|
c-0.011-0.028,0.014-0.046,0.062-0.065c0.105-0.048,0.208-0.144,0.263-0.267c0.073-0.164,0.056-0.472-0.076-0.79
|
||||||
|
c-0.125-0.3-0.282-0.466-0.483-0.561c-0.335-0.156-0.69-0.086-1.025,0.053c-0.822,0.34-0.972,1.134-0.78,1.597
|
||||||
|
c0.127,0.309,0.239,0.48,0.455,0.554c0.09,0.03,0.209,0.034,0.275,0.022c0.061-0.012,0.076-0.011,0.089,0.017
|
||||||
|
c0.01,0.023-0.012,0.042-0.039,0.053c-0.041,0.017-0.359,0.1-0.491,0.114c-0.066,0.007-0.089,0-0.137-0.05
|
||||||
|
c-0.113-0.114-0.246-0.367-0.338-0.589C40.232,17.361,40.171,16.92,40.314,16.493z M42.775,19.295
|
||||||
|
c0.555-0.125,0.657-0.146,0.771-0.181c0.123-0.035,0.175-0.077,0.174-0.204c0-0.031-0.01-0.094-0.021-0.145
|
||||||
|
c-0.009-0.04-0.007-0.064,0.019-0.069c0.026-0.006,0.039,0.018,0.052,0.073c0.021,0.099,0.042,0.205,0.062,0.296
|
||||||
|
c0.019,0.096,0.033,0.181,0.044,0.23c0.026,0.117,0.189,0.844,0.208,0.912c0.023,0.068,0.043,0.125,0.058,0.152
|
||||||
|
c0.008,0.018,0.023,0.037,0.027,0.056s-0.01,0.025-0.027,0.029c-0.025,0.005-0.073-0.003-0.244,0.023
|
||||||
|
c-0.038,0.005-0.2,0.033-0.245,0.036c-0.02,0-0.042-0.002-0.048-0.026c-0.006-0.025,0.011-0.037,0.043-0.044
|
||||||
|
c0.025-0.005,0.087-0.023,0.126-0.052c0.06-0.041,0.096-0.087,0.077-0.273c-0.006-0.063-0.085-0.448-0.103-0.521
|
||||||
|
c-0.004-0.018-0.017-0.022-0.042-0.017l-0.923,0.208c-0.026,0.006-0.04,0.013-0.035,0.034c0.019,0.081,0.112,0.5,0.14,0.583
|
||||||
|
c0.026,0.086,0.05,0.138,0.094,0.163c0.035,0.019,0.056,0.028,0.061,0.047c0.003,0.015-0.001,0.026-0.022,0.032
|
||||||
|
c-0.022,0.005-0.083,0.003-0.273,0.03c-0.074,0.014-0.223,0.035-0.248,0.041c-0.028,0.006-0.068,0.017-0.077-0.018
|
||||||
|
c-0.006-0.025,0.008-0.036,0.025-0.04c0.036-0.012,0.083-0.022,0.128-0.044c0.069-0.035,0.112-0.099,0.096-0.236
|
||||||
|
c-0.008-0.071-0.086-0.434-0.104-0.521c-0.004-0.019-0.021-0.02-0.042-0.015l-0.288,0.065c-0.124,0.028-0.461,0.1-0.566,0.127
|
||||||
|
c-0.25,0.062-0.292,0.134-0.208,0.507c0.021,0.095,0.057,0.248,0.121,0.333c0.065,0.085,0.152,0.112,0.308,0.104
|
||||||
|
c0.042-0.001,0.058,0.002,0.063,0.027c0.006,0.029-0.022,0.036-0.06,0.044c-0.084,0.02-0.338,0.045-0.416,0.043
|
||||||
|
c-0.102-0.004-0.108-0.037-0.14-0.176c-0.062-0.272-0.099-0.476-0.131-0.634c-0.027-0.158-0.05-0.272-0.074-0.382
|
||||||
|
c-0.009-0.04-0.026-0.121-0.05-0.207c-0.019-0.084-0.047-0.177-0.063-0.25c-0.012-0.047-0.006-0.075,0.02-0.081
|
||||||
|
c0.019-0.004,0.033,0.008,0.042,0.052c0.012,0.055,0.029,0.097,0.044,0.128c0.031,0.069,0.115,0.07,0.226,0.062
|
||||||
|
c0.156-0.017,0.445-0.081,0.78-0.156L42.775,19.295z M42.087,22.487c-0.292,0.018-0.387,0.07-0.41,0.146
|
||||||
|
c-0.021,0.064-0.021,0.137-0.02,0.195c0.001,0.041-0.005,0.064-0.027,0.064c-0.029,0.001-0.039-0.032-0.041-0.084
|
||||||
|
c-0.009-0.243-0.003-0.394-0.005-0.465c-0.001-0.033-0.019-0.209-0.024-0.402c-0.002-0.048,0.001-0.083,0.033-0.083
|
||||||
|
c0.022-0.001,0.031,0.021,0.032,0.059c0.002,0.049,0.008,0.116,0.024,0.167c0.034,0.097,0.143,0.107,0.468,0.101l2.214-0.044
|
||||||
|
c0.075-0.003,0.128,0.007,0.129,0.044c0.001,0.041-0.046,0.075-0.11,0.143c-0.048,0.046-0.637,0.636-1.159,1.201
|
||||||
|
c-0.245,0.263-0.767,0.787-0.823,0.852v0.02l1.677-0.098c0.229-0.012,0.298-0.048,0.332-0.139c0.021-0.057,0.018-0.146,0.016-0.199
|
||||||
|
c-0.001-0.045,0.009-0.061,0.031-0.061c0.03-0.001,0.035,0.04,0.037,0.095c0.007,0.194,0.002,0.375,0.005,0.453
|
||||||
|
c0.001,0.041,0.019,0.183,0.024,0.366c0.001,0.049,0,0.086-0.031,0.087c-0.021,0.001-0.034-0.021-0.036-0.066
|
||||||
|
c-0.001-0.038-0.002-0.066-0.015-0.111c-0.034-0.104-0.113-0.132-0.323-0.127l-2.359,0.042c-0.082,0.003-0.116-0.011-0.118-0.044
|
||||||
|
c-0.001-0.041,0.038-0.088,0.078-0.13c0.216-0.243,0.688-0.738,1.06-1.142c0.39-0.421,0.842-0.853,0.911-0.923v-0.011L42.087,22.487
|
||||||
|
z M41.585,25.938c0.035-0.057,0.056-0.064,0.137-0.054c0.203,0.03,0.424,0.076,0.481,0.09c0.055,0.012,0.094,0.027,0.09,0.058
|
||||||
|
c-0.004,0.034-0.038,0.032-0.067,0.028c-0.049-0.008-0.128-0.003-0.194,0.006c-0.286,0.042-0.417,0.246-0.45,0.476
|
||||||
|
c-0.048,0.333,0.154,0.528,0.352,0.558c0.182,0.025,0.359-0.006,0.645-0.277l0.158-0.151c0.377-0.36,0.656-0.465,0.956-0.422
|
||||||
|
c0.407,0.06,0.649,0.441,0.577,0.956c-0.035,0.24-0.095,0.392-0.135,0.483c-0.012,0.031-0.025,0.049-0.052,0.045
|
||||||
|
c-0.048-0.007-0.152-0.037-0.441-0.078c-0.082-0.012-0.109-0.027-0.105-0.057c0.004-0.026,0.027-0.034,0.072-0.027
|
||||||
|
c0.033,0.004,0.149,0.002,0.258-0.062c0.078-0.046,0.205-0.137,0.239-0.378c0.04-0.272-0.097-0.463-0.318-0.495
|
||||||
|
c-0.17-0.023-0.312,0.042-0.589,0.316l-0.093,0.093c-0.401,0.398-0.68,0.521-1.031,0.472c-0.215-0.03-0.458-0.148-0.594-0.44
|
||||||
|
c-0.092-0.202-0.097-0.414-0.067-0.61C41.442,26.249,41.492,26.087,41.585,25.938z M42.705,29.112
|
||||||
|
c0.547,0.154,0.648,0.183,0.766,0.208c0.125,0.027,0.195,0.009,0.235-0.065c0.022-0.036,0.039-0.082,0.051-0.125
|
||||||
|
c0.011-0.036,0.023-0.056,0.053-0.048c0.021,0.007,0.021,0.037,0.004,0.095c-0.039,0.138-0.113,0.36-0.144,0.466
|
||||||
|
c-0.024,0.09-0.073,0.305-0.112,0.44c-0.014,0.047-0.028,0.074-0.051,0.068c-0.028-0.009-0.029-0.032-0.02-0.068
|
||||||
|
s0.015-0.064,0.02-0.11c0.01-0.103-0.044-0.147-0.168-0.19c-0.112-0.04-0.213-0.068-0.76-0.223l-0.633-0.181
|
||||||
|
c-0.349-0.099-0.633-0.179-0.792-0.208c-0.1-0.017-0.172-0.01-0.217,0.095c-0.021,0.049-0.051,0.126-0.066,0.18
|
||||||
|
c-0.011,0.04-0.026,0.055-0.045,0.05c-0.025-0.007-0.028-0.039-0.017-0.079c0.066-0.236,0.142-0.461,0.169-0.559
|
||||||
|
c0.022-0.082,0.077-0.312,0.118-0.456c0.013-0.047,0.03-0.068,0.056-0.062c0.018,0.005,0.025,0.022,0.013,0.066
|
||||||
|
c-0.016,0.053-0.021,0.099-0.021,0.133c-0.006,0.076,0.049,0.115,0.149,0.155c0.146,0.061,0.431,0.141,0.779,0.239L42.705,29.112z
|
||||||
|
M40.502,30.431c0.048-0.046,0.069-0.048,0.146-0.016c0.188,0.081,0.389,0.186,0.441,0.211c0.051,0.026,0.083,0.054,0.072,0.08
|
||||||
|
c-0.013,0.031-0.046,0.021-0.073,0.009c-0.044-0.019-0.123-0.035-0.188-0.044c-0.287-0.033-0.467,0.128-0.56,0.342
|
||||||
|
c-0.134,0.309,0.011,0.55,0.192,0.629c0.168,0.071,0.348,0.09,0.694-0.101l0.191-0.104c0.458-0.25,0.755-0.277,1.033-0.156
|
||||||
|
c0.377,0.163,0.512,0.596,0.306,1.072c-0.097,0.224-0.192,0.353-0.256,0.432c-0.02,0.028-0.038,0.041-0.062,0.03
|
||||||
|
c-0.044-0.021-0.139-0.076-0.406-0.192c-0.075-0.032-0.099-0.055-0.086-0.082c0.01-0.022,0.035-0.024,0.077-0.007
|
||||||
|
c0.031,0.013,0.145,0.042,0.265,0.009c0.088-0.022,0.233-0.079,0.33-0.302c0.11-0.254,0.029-0.473-0.177-0.562
|
||||||
|
c-0.158-0.068-0.312-0.041-0.651,0.149l-0.113,0.064c-0.492,0.28-0.792,0.325-1.119,0.185c-0.199-0.086-0.403-0.264-0.458-0.58
|
||||||
|
c-0.036-0.22,0.017-0.425,0.095-0.606C40.282,30.694,40.373,30.55,40.502,30.431z M13.791,41.773c-0.024,0-0.056-0.002-0.114-0.02
|
||||||
|
c-0.053-0.015-0.07-0.058-0.09-0.186l-0.189-1.25c-0.009-0.048-0.034-0.077-0.064-0.079c-0.029,0.001-0.052,0.024-0.069,0.06
|
||||||
|
l-0.548,1.112l-0.546-1.098c-0.026-0.057-0.05-0.074-0.08-0.074c-0.029,0.001-0.052,0.029-0.057,0.066l-0.207,1.321
|
||||||
|
c-0.009,0.067-0.032,0.141-0.071,0.142c-0.032,0.004-0.046,0.004-0.062,0.004c-0.025,0-0.049,0.012-0.05,0.037
|
||||||
|
c0,0.032,0.033,0.04,0.055,0.04c0.068,0,0.168-0.008,0.208-0.008c0.037,0,0.132,0.008,0.221,0.008c0.029,0,0.065-0.005,0.067-0.04
|
||||||
|
c-0.003-0.027-0.026-0.036-0.05-0.037c-0.018,0-0.035-0.002-0.07-0.009c-0.035-0.009-0.05-0.017-0.051-0.044
|
||||||
|
c0-0.031,0.002-0.058,0.007-0.093l0.094-0.746c0.07,0.145,0.175,0.359,0.19,0.395c0.024,0.06,0.19,0.367,0.241,0.461
|
||||||
|
c0.034,0.061,0.054,0.105,0.099,0.111c0.04-0.004,0.051-0.031,0.099-0.124l0.432-0.866l0.109,0.832
|
||||||
|
c0.002,0.018,0.003,0.032,0.003,0.043c0,0.023-0.003,0.022-0.002,0.024c-0.015,0.006-0.033,0.015-0.035,0.037
|
||||||
|
c0.003,0.029,0.029,0.039,0.078,0.041c0.084,0.005,0.382,0.015,0.436,0.015c0.031-0.001,0.066-0.003,0.071-0.04
|
||||||
|
C13.839,41.781,13.812,41.773,13.791,41.773z M15.5,40.521c-0.234-0.237-0.593-0.235-0.854-0.235c-0.126,0-0.277,0.004-0.341,0.004
|
||||||
|
c-0.06,0-0.193-0.004-0.303-0.004c-0.028,0-0.062,0.002-0.064,0.035c0.001,0.029,0.029,0.039,0.053,0.039
|
||||||
|
c0.03,0,0.066,0.002,0.079,0.006c0.063,0.021,0.071,0.028,0.078,0.095c0.003,0.063,0.003,0.12,0.003,0.429v0.355
|
||||||
|
c0,0.188,0,0.346-0.01,0.43c-0.009,0.061-0.019,0.086-0.05,0.094c-0.018,0.004-0.04,0.006-0.069,0.006
|
||||||
|
c-0.031,0-0.05,0.02-0.05,0.039c0.001,0.028,0.029,0.038,0.058,0.038c0.043,0,0.096-0.002,0.146-0.005
|
||||||
|
c0.051,0,0.097-0.003,0.119-0.003c0.052,0,0.127,0.006,0.21,0.013c0.083,0.005,0.175,0.012,0.251,0.012
|
||||||
|
c0.391,0,0.616-0.145,0.715-0.243c0.121-0.119,0.233-0.315,0.233-0.576C15.703,40.802,15.607,40.629,15.5,40.521z M15.368,41.105
|
||||||
|
c0,0.207-0.042,0.382-0.172,0.488c-0.123,0.103-0.258,0.135-0.446,0.135c-0.162,0.001-0.24-0.044-0.26-0.073
|
||||||
|
c-0.011-0.012-0.02-0.086-0.021-0.134c-0.003-0.04-0.006-0.195-0.006-0.409v-0.255c0-0.159,0-0.326,0.003-0.396
|
||||||
|
c0.003-0.021,0-0.018,0.016-0.024c0.009-0.007,0.082-0.015,0.123-0.014c0.163,0,0.386,0.021,0.574,0.188
|
||||||
|
C15.268,40.69,15.368,40.853,15.368,41.105z M17.351,41.434c-0.028-0.001-0.041,0.025-0.042,0.055
|
||||||
|
c-0.006,0.033-0.034,0.09-0.068,0.127c-0.078,0.087-0.173,0.102-0.358,0.102c-0.272-0.001-0.635-0.222-0.636-0.691
|
||||||
|
c0-0.196,0.038-0.386,0.188-0.514c0.091-0.077,0.203-0.11,0.384-0.11c0.189,0,0.327,0.05,0.393,0.114
|
||||||
|
c0.049,0.049,0.074,0.116,0.076,0.177c0,0.023,0.004,0.058,0.039,0.06c0.036-0.003,0.043-0.038,0.045-0.065
|
||||||
|
c0.002-0.041,0.002-0.153,0.007-0.22c0.004-0.07,0.01-0.094,0.01-0.112c0.002-0.021-0.02-0.04-0.047-0.04
|
||||||
|
c-0.061-0.008-0.129-0.022-0.208-0.034c-0.096-0.012-0.176-0.021-0.308-0.021c-0.313,0-0.52,0.083-0.675,0.22
|
||||||
|
c-0.205,0.184-0.251,0.426-0.251,0.566c0,0.198,0.056,0.435,0.268,0.61c0.195,0.164,0.442,0.224,0.73,0.224
|
||||||
|
c0.137,0,0.296-0.012,0.385-0.047c0.037-0.013,0.057-0.033,0.065-0.069c0.021-0.072,0.045-0.245,0.045-0.273
|
||||||
|
C17.391,41.465,17.382,41.437,17.351,41.434z M19.029,41.434c-0.028-0.001-0.041,0.025-0.043,0.055
|
||||||
|
c-0.005,0.033-0.034,0.09-0.067,0.127c-0.079,0.087-0.173,0.102-0.358,0.102c-0.273-0.001-0.636-0.222-0.637-0.691
|
||||||
|
c0-0.196,0.038-0.386,0.188-0.514c0.092-0.077,0.203-0.11,0.384-0.11c0.19,0,0.327,0.05,0.394,0.114
|
||||||
|
c0.049,0.049,0.072,0.116,0.075,0.177c0,0.023,0.006,0.058,0.039,0.06c0.037-0.003,0.043-0.038,0.045-0.065
|
||||||
|
c0.002-0.041,0.002-0.153,0.008-0.22c0.004-0.07,0.009-0.094,0.01-0.112c0.001-0.021-0.021-0.04-0.047-0.04
|
||||||
|
c-0.062-0.008-0.129-0.022-0.208-0.034c-0.097-0.012-0.177-0.021-0.308-0.021c-0.314,0-0.521,0.083-0.676,0.22
|
||||||
|
c-0.205,0.184-0.251,0.426-0.251,0.566c0,0.198,0.056,0.435,0.269,0.61c0.194,0.164,0.441,0.224,0.729,0.224
|
||||||
|
c0.137,0,0.297-0.012,0.385-0.047c0.037-0.013,0.058-0.033,0.064-0.069c0.021-0.072,0.045-0.245,0.046-0.273
|
||||||
|
C19.069,41.465,19.06,41.437,19.029,41.434z M20.707,41.434c-0.027-0.001-0.041,0.025-0.043,0.055
|
||||||
|
c-0.006,0.033-0.034,0.09-0.066,0.127c-0.079,0.087-0.174,0.102-0.359,0.102c-0.272-0.001-0.635-0.222-0.635-0.691
|
||||||
|
c0-0.196,0.037-0.386,0.187-0.514c0.092-0.077,0.203-0.11,0.385-0.11c0.189,0,0.327,0.05,0.394,0.114
|
||||||
|
c0.049,0.049,0.074,0.116,0.076,0.177c0,0.023,0.005,0.058,0.039,0.06c0.037-0.003,0.043-0.038,0.045-0.065
|
||||||
|
c0.002-0.041,0.002-0.153,0.007-0.22c0.005-0.07,0.009-0.094,0.009-0.112c0.002-0.021-0.019-0.04-0.046-0.04
|
||||||
|
c-0.061-0.008-0.129-0.022-0.209-0.034c-0.095-0.012-0.175-0.021-0.307-0.021c-0.314,0-0.521,0.083-0.677,0.22
|
||||||
|
c-0.205,0.184-0.251,0.426-0.251,0.566c0,0.198,0.057,0.435,0.269,0.61c0.194,0.164,0.441,0.224,0.729,0.224
|
||||||
|
c0.138,0,0.297-0.012,0.386-0.047c0.036-0.013,0.057-0.033,0.064-0.069c0.022-0.072,0.045-0.245,0.046-0.273
|
||||||
|
C20.747,41.465,20.738,41.437,20.707,41.434z M28.803,41.773c-0.019,0-0.051-0.002-0.076-0.011
|
||||||
|
c-0.043-0.015-0.072-0.032-0.106-0.075c-0.049-0.061-0.379-0.581-0.459-0.703l0.34-0.465c0.064-0.089,0.104-0.141,0.142-0.148
|
||||||
|
c0.027-0.007,0.053-0.011,0.071-0.011c0.025,0,0.05-0.014,0.051-0.039c-0.002-0.031-0.032-0.036-0.056-0.036
|
||||||
|
c-0.08,0-0.166,0.005-0.205,0.005c-0.04,0-0.138-0.005-0.22-0.005c-0.029,0-0.06,0.005-0.062,0.036
|
||||||
|
c0.001,0.028,0.025,0.039,0.043,0.039c0.017,0,0.044,0,0.062,0.006c0.019,0.004,0.024,0.015,0.024,0.018
|
||||||
|
c0,0.013-0.006,0.039-0.022,0.064c-0.032,0.053-0.195,0.293-0.268,0.399c-0.079-0.132-0.161-0.266-0.248-0.418
|
||||||
|
c-0.011-0.02-0.021-0.047-0.021-0.052c0-0.002,0.002-0.009,0.017-0.013s0.036-0.006,0.046-0.006c0.021,0,0.049-0.01,0.05-0.039
|
||||||
|
c-0.002-0.031-0.033-0.036-0.06-0.036c-0.079,0-0.208,0.005-0.236,0.005c-0.101,0-0.269-0.005-0.319-0.005
|
||||||
|
c-0.024,0.001-0.055,0.001-0.06,0.034c0,0.021,0.016,0.041,0.038,0.041c0.019,0,0.051,0.004,0.083,0.014
|
||||||
|
c0.068,0.022,0.106,0.062,0.16,0.142l0.361,0.564l-0.401,0.544c-0.072,0.099-0.102,0.125-0.158,0.142
|
||||||
|
c-0.028,0.007-0.06,0.009-0.072,0.009c-0.024,0.001-0.045,0.018-0.045,0.041s0.024,0.036,0.048,0.036h0.036
|
||||||
|
c0.034,0,0.137-0.008,0.176-0.008c0.052,0,0.189,0.008,0.203,0.008h0.038c0.027,0,0.058-0.004,0.06-0.036
|
||||||
|
c-0.002-0.025-0.021-0.039-0.043-0.041c-0.015,0-0.03-0.002-0.045-0.002c-0.013,0-0.022-0.01-0.022-0.018c0-0.001,0-0.003,0-0.003
|
||||||
|
c0-0.015,0.01-0.042,0.028-0.07l0.293-0.453c0.093,0.149,0.201,0.332,0.316,0.52c0.004,0.007,0.005,0.012,0.005,0.014
|
||||||
|
c0,0.005-0.002,0.005-0.002,0.005c-0.021,0.005-0.041,0.021-0.041,0.043c0.006,0.036,0.038,0.034,0.09,0.038
|
||||||
|
c0.172,0.005,0.339,0.005,0.39,0.005h0.062c0.024,0,0.055-0.008,0.059-0.038C28.846,41.788,28.824,41.773,28.803,41.773z
|
||||||
|
M30.581,41.773c-0.018,0-0.05-0.002-0.076-0.011c-0.043-0.015-0.071-0.032-0.105-0.075c-0.049-0.061-0.379-0.581-0.46-0.703
|
||||||
|
l0.341-0.465c0.064-0.089,0.104-0.141,0.141-0.148c0.028-0.007,0.054-0.011,0.072-0.011c0.025,0,0.05-0.014,0.05-0.039
|
||||||
|
c-0.001-0.031-0.031-0.036-0.055-0.036c-0.079,0-0.165,0.005-0.205,0.005s-0.138-0.005-0.219-0.005
|
||||||
|
c-0.029,0-0.062,0.005-0.062,0.036c0.001,0.028,0.026,0.039,0.043,0.039c0.018,0,0.044,0,0.062,0.006
|
||||||
|
c0.019,0.004,0.024,0.015,0.023,0.018c0,0.013-0.006,0.039-0.021,0.064c-0.032,0.053-0.195,0.293-0.269,0.399
|
||||||
|
c-0.078-0.133-0.16-0.266-0.247-0.418c-0.012-0.02-0.021-0.047-0.02-0.052c0-0.002,0.001-0.008,0.016-0.013
|
||||||
|
c0.016-0.004,0.036-0.006,0.047-0.006c0.021,0,0.049-0.01,0.05-0.039c-0.002-0.031-0.033-0.036-0.061-0.036
|
||||||
|
c-0.079,0-0.208,0.005-0.234,0.005c-0.101,0-0.27-0.005-0.319-0.005c-0.025,0.001-0.055,0.001-0.06,0.034
|
||||||
|
c0,0.021,0.017,0.041,0.037,0.041s0.053,0.004,0.083,0.014c0.069,0.022,0.107,0.062,0.16,0.142l0.362,0.564l-0.402,0.544
|
||||||
|
c-0.071,0.099-0.101,0.125-0.157,0.142c-0.029,0.007-0.06,0.009-0.071,0.009c-0.025,0.001-0.045,0.018-0.046,0.041
|
||||||
|
c0,0.023,0.023,0.036,0.048,0.036h0.036c0.035,0,0.137-0.008,0.176-0.008c0.052,0,0.189,0.008,0.203,0.008h0.038
|
||||||
|
c0.026,0,0.058-0.004,0.06-0.036c-0.002-0.025-0.021-0.039-0.043-0.041c-0.015,0-0.031-0.002-0.045-0.002
|
||||||
|
c-0.013,0-0.022-0.008-0.023-0.018c0-0.001,0-0.003,0-0.003c0-0.015,0.01-0.042,0.028-0.07l0.292-0.453
|
||||||
|
c0.092,0.149,0.201,0.332,0.317,0.52c0.004,0.007,0.005,0.012,0.005,0.014c0,0.004-0.002,0.005-0.002,0.005
|
||||||
|
c-0.021,0.005-0.041,0.021-0.041,0.043c0.006,0.036,0.038,0.034,0.09,0.038c0.171,0.005,0.338,0.005,0.389,0.005h0.062
|
||||||
|
c0.024,0,0.055-0.008,0.058-0.038C30.624,41.788,30.603,41.773,30.581,41.773z M32.359,41.773c-0.019,0-0.05-0.002-0.076-0.011
|
||||||
|
c-0.043-0.015-0.072-0.032-0.106-0.075c-0.049-0.061-0.379-0.581-0.459-0.703l0.341-0.465c0.063-0.089,0.104-0.141,0.141-0.148
|
||||||
|
c0.028-0.007,0.053-0.011,0.072-0.011c0.024,0,0.049-0.014,0.05-0.039c-0.002-0.031-0.032-0.036-0.055-0.036
|
||||||
|
c-0.079,0-0.166,0.005-0.205,0.005c-0.04,0-0.139-0.005-0.22-0.005c-0.028,0-0.061,0.005-0.062,0.036
|
||||||
|
c0.001,0.028,0.025,0.039,0.043,0.039c0.016,0,0.044,0,0.061,0.006c0.02,0.004,0.025,0.015,0.024,0.018
|
||||||
|
c0,0.013-0.006,0.039-0.021,0.064c-0.032,0.053-0.195,0.293-0.269,0.399c-0.079-0.132-0.161-0.266-0.248-0.418
|
||||||
|
c-0.011-0.02-0.02-0.047-0.02-0.052c0-0.002,0.002-0.009,0.016-0.013c0.015-0.004,0.036-0.006,0.046-0.006
|
||||||
|
c0.021,0,0.049-0.01,0.05-0.039c-0.002-0.031-0.032-0.036-0.06-0.036c-0.079,0-0.208,0.005-0.236,0.005
|
||||||
|
c-0.099,0-0.268-0.005-0.317-0.005c-0.026,0.001-0.057,0.001-0.061,0.034c0,0.021,0.018,0.041,0.038,0.041
|
||||||
|
c0.02,0,0.052,0.004,0.083,0.014c0.069,0.022,0.107,0.062,0.159,0.142l0.363,0.564l-0.402,0.544
|
||||||
|
c-0.072,0.099-0.101,0.125-0.157,0.142c-0.029,0.007-0.059,0.009-0.072,0.009c-0.023,0.001-0.045,0.018-0.045,0.041
|
||||||
|
s0.024,0.036,0.047,0.036h0.036c0.035,0,0.138-0.008,0.177-0.008c0.052,0,0.188,0.008,0.201,0.008h0.038
|
||||||
|
c0.027,0,0.059-0.004,0.061-0.036c-0.002-0.025-0.021-0.039-0.043-0.041c-0.017,0-0.032-0.002-0.045-0.002
|
||||||
|
c-0.014,0-0.023-0.008-0.024-0.018v-0.003c0-0.015,0.01-0.042,0.028-0.07l0.293-0.453c0.092,0.149,0.201,0.332,0.315,0.52
|
||||||
|
c0.004,0.007,0.006,0.012,0.006,0.014c0,0.004-0.003,0.005-0.003,0.005c-0.021,0.005-0.041,0.021-0.041,0.043
|
||||||
|
c0.007,0.036,0.038,0.033,0.091,0.038c0.172,0.005,0.339,0.005,0.389,0.005h0.062c0.025,0,0.056-0.008,0.059-0.038
|
||||||
|
C32.401,41.788,32.38,41.773,32.359,41.773z M33.453,41.773c-0.03,0-0.078-0.002-0.104-0.007c-0.057-0.012-0.061-0.026-0.069-0.08
|
||||||
|
c-0.009-0.084-0.009-0.246-0.009-0.44v-0.356c0-0.309,0-0.364,0.004-0.429c0.007-0.069,0.015-0.083,0.063-0.094
|
||||||
|
c0.024-0.005,0.039-0.007,0.06-0.007s0.051-0.012,0.051-0.041c-0.005-0.033-0.035-0.033-0.061-0.034
|
||||||
|
c-0.081,0-0.218,0.005-0.27,0.005c-0.059,0-0.202-0.005-0.281-0.005c-0.031,0.001-0.062,0-0.066,0.034
|
||||||
|
c0,0.029,0.028,0.041,0.051,0.041c0.025,0,0.05,0.002,0.071,0.009c0.04,0.015,0.053,0.025,0.06,0.092
|
||||||
|
c0.002,0.063,0.002,0.12,0.002,0.429v0.356c0,0.194,0,0.356-0.01,0.438c-0.009,0.06-0.015,0.073-0.049,0.083
|
||||||
|
c-0.018,0.004-0.04,0.006-0.07,0.006c-0.031,0-0.051,0.02-0.051,0.039c0.001,0.029,0.031,0.038,0.058,0.038
|
||||||
|
c0.084,0,0.228-0.008,0.273-0.008c0.056,0,0.2,0.008,0.338,0.008c0.025,0,0.055-0.008,0.058-0.038
|
||||||
|
C33.504,41.791,33.482,41.773,33.453,41.773z M34.724,41.773c-0.03,0-0.078-0.002-0.104-0.007c-0.056-0.012-0.06-0.026-0.069-0.08
|
||||||
|
c-0.01-0.084-0.01-0.246-0.01-0.44v-0.356c0-0.309,0-0.364,0.005-0.429c0.008-0.069,0.015-0.083,0.064-0.094
|
||||||
|
c0.023-0.005,0.039-0.007,0.059-0.007c0.021,0,0.051-0.012,0.051-0.041c-0.006-0.033-0.034-0.033-0.061-0.034
|
||||||
|
c-0.082,0-0.218,0.005-0.27,0.005c-0.06,0-0.202-0.005-0.281-0.005c-0.032,0.001-0.062,0-0.067,0.034
|
||||||
|
c0,0.029,0.029,0.041,0.05,0.041c0.025,0,0.051,0.002,0.071,0.009c0.04,0.015,0.052,0.025,0.06,0.092
|
||||||
|
c0.003,0.063,0.003,0.12,0.003,0.429v0.356c0,0.194,0,0.356-0.011,0.438c-0.009,0.06-0.015,0.073-0.049,0.083
|
||||||
|
c-0.018,0.004-0.04,0.006-0.069,0.006c-0.031,0-0.051,0.02-0.051,0.039c0.001,0.029,0.03,0.038,0.058,0.038
|
||||||
|
c0.084,0,0.227-0.008,0.273-0.008c0.057,0,0.2,0.008,0.338,0.008c0.025,0,0.056-0.008,0.059-0.038
|
||||||
|
C34.774,41.791,34.753,41.773,34.724,41.773z M35.995,41.773c-0.03,0-0.077-0.002-0.104-0.007c-0.057-0.012-0.061-0.026-0.069-0.08
|
||||||
|
c-0.01-0.084-0.01-0.246-0.01-0.44v-0.356c0-0.309,0-0.364,0.005-0.429c0.007-0.069,0.014-0.083,0.063-0.094
|
||||||
|
c0.024-0.005,0.039-0.007,0.06-0.007s0.05-0.012,0.05-0.041c-0.005-0.033-0.035-0.033-0.06-0.034c-0.081,0-0.218,0.005-0.27,0.005
|
||||||
|
c-0.059,0-0.202-0.005-0.281-0.005c-0.031,0.001-0.062,0-0.066,0.034c0,0.029,0.028,0.041,0.05,0.041
|
||||||
|
c0.025,0,0.05,0.002,0.071,0.009c0.041,0.015,0.053,0.025,0.06,0.092c0.002,0.063,0.002,0.12,0.002,0.429v0.356
|
||||||
|
c0,0.194,0,0.356-0.009,0.438c-0.009,0.06-0.015,0.073-0.049,0.083c-0.019,0.004-0.04,0.006-0.07,0.006
|
||||||
|
c-0.031,0-0.05,0.02-0.05,0.039c0.001,0.029,0.031,0.038,0.058,0.038c0.084,0,0.228-0.008,0.274-0.008
|
||||||
|
c0.056,0,0.2,0.008,0.338,0.008c0.024,0,0.055-0.008,0.057-0.038C36.045,41.79,36.024,41.773,35.995,41.773z M23.406,31.974v-1.188
|
||||||
|
c0-0.222-0.18-0.402-0.402-0.402c-0.222,0-0.402,0.182-0.402,0.402v1.188H23.406z M25.583,31.974v-1.188
|
||||||
|
c0-0.222-0.18-0.402-0.401-0.402c-0.224,0-0.403,0.182-0.403,0.402v1.188H25.583z M24.092,8.076c-0.232,0-0.422,0.189-0.422,0.422
|
||||||
|
c0,0.233,0.189,0.422,0.422,0.422c0.233,0,0.423-0.188,0.423-0.422C24.514,8.265,24.325,8.076,24.092,8.076z M23.879,19.853h0.426
|
||||||
|
v-0.915h-0.426V19.853L23.879,19.853z M19.84,42.941c-0.232,0-0.422,0.188-0.422,0.422s0.189,0.422,0.422,0.422
|
||||||
|
c0.233,0,0.423-0.188,0.423-0.422S20.073,42.941,19.84,42.941z M19.584,19.869v-1.345c-0.003-0.315-0.158-0.533-0.39-0.635
|
||||||
|
c-0.231,0.102-0.386,0.319-0.389,0.636v1.344H19.584z M19.584,15.548V14.68c-0.003-0.315-0.158-0.534-0.39-0.637
|
||||||
|
c-0.231,0.104-0.386,0.321-0.389,0.637v0.867H19.584z M19.402,24.539v-1.127c0-0.116-0.093-0.209-0.209-0.209
|
||||||
|
s-0.209,0.093-0.209,0.209v1.127H19.402z M19.402,27.931v-1.126c0-0.116-0.093-0.211-0.209-0.211s-0.209,0.095-0.209,0.211v1.126
|
||||||
|
H19.402z M19.525,31.721v-1c0-0.188-0.151-0.339-0.338-0.339c-0.188,0-0.338,0.151-0.338,0.339v1H19.525z M19.194,3.409
|
||||||
|
c-0.233,0-0.422,0.189-0.422,0.422c0,0.233,0.188,0.422,0.422,0.422c0.232,0,0.422-0.188,0.422-0.422
|
||||||
|
C19.616,3.598,19.427,3.409,19.194,3.409z M29.375,19.869v-1.345c-0.002-0.315-0.158-0.533-0.389-0.635
|
||||||
|
c-0.231,0.102-0.387,0.319-0.389,0.636v1.344H29.375z M29.375,15.548V14.68c-0.002-0.315-0.158-0.534-0.389-0.637
|
||||||
|
c-0.231,0.104-0.387,0.321-0.389,0.637v0.867H29.375z M29.194,24.539v-1.127c0-0.116-0.094-0.209-0.209-0.209
|
||||||
|
s-0.209,0.093-0.209,0.209v1.127H29.194z M29.194,27.931v-1.126c0-0.116-0.094-0.211-0.209-0.211s-0.209,0.095-0.209,0.211v1.126
|
||||||
|
H29.194z M29.317,31.721v-1c0-0.188-0.151-0.339-0.338-0.339c-0.188,0-0.338,0.151-0.338,0.339v1H29.317z M28.985,3.409
|
||||||
|
c-0.233,0-0.422,0.189-0.422,0.422c0,0.233,0.188,0.422,0.422,0.422c0.232,0,0.422-0.188,0.422-0.422
|
||||||
|
C29.408,3.598,29.219,3.409,28.985,3.409z M60.109,21.36c-3.838,0-4.703-2.09-4.703-4.415V8.998h2.342v7.803
|
||||||
|
c0,1.532,0.505,2.613,2.523,2.613c1.802,0,2.559-0.757,2.559-2.829V8.998h2.325v7.442C65.155,19.774,63.316,21.36,60.109,21.36z
|
||||||
|
M73.155,21.162v-5.729c0-0.938-0.253-1.496-1.1-1.496c-1.172,0-2.091,1.334-2.091,2.901v4.325h-2.307v-8.956h2.181
|
||||||
|
c0,0.415-0.035,1.117-0.126,1.586l0.019,0.019c0.541-1.063,1.586-1.803,3.046-1.803c2.018,0,2.666,1.298,2.666,2.865v6.289
|
||||||
|
L73.155,21.162L73.155,21.162z M79.102,11.052c-0.793,0-1.424-0.631-1.424-1.405c0-0.757,0.631-1.389,1.424-1.389
|
||||||
|
s1.44,0.613,1.44,1.389C80.543,10.422,79.895,11.052,79.102,11.052z M77.948,21.162v-8.956h2.307v8.956H77.948z M87.211,21.162
|
||||||
|
h-2.343l-3.314-8.956h2.521l1.424,4.036c0.216,0.613,0.434,1.334,0.596,1.982h0.035c0.145-0.612,0.324-1.298,0.54-1.91l1.441-4.108
|
||||||
|
h2.451L87.211,21.162z M98.797,17.054h-5.551c-0.018,1.676,0.812,2.485,2.469,2.485c0.884,0,1.839-0.198,2.613-0.559l0.216,1.784
|
||||||
|
c-0.955,0.378-2.09,0.576-3.207,0.576c-2.848,0-4.433-1.423-4.433-4.576c0-2.739,1.514-4.758,4.198-4.758
|
||||||
|
c2.611,0,3.767,1.784,3.767,4C98.869,16.314,98.851,16.675,98.797,17.054z M95.03,13.702c-0.955,0-1.622,0.703-1.748,1.784h3.298
|
||||||
|
C96.616,14.368,96.004,13.702,95.03,13.702z M105.59,14.278c-1.657-0.343-2.485,0.739-2.485,3.226v3.658h-2.308v-8.956h2.181
|
||||||
|
c0,0.45-0.055,1.171-0.162,1.802h0.036c0.433-1.135,1.298-2.126,2.848-2L105.59,14.278z M108.743,21.342
|
||||||
|
c-0.647,0-1.298-0.071-1.874-0.161l0.055-1.893c0.559,0.145,1.242,0.271,1.929,0.271c0.883,0,1.459-0.361,1.459-0.956
|
||||||
|
c0-1.585-3.621-0.686-3.621-3.73c0-1.567,1.278-2.865,3.802-2.865c0.522,0,1.1,0.072,1.64,0.162l-0.07,1.82
|
||||||
|
c-0.505-0.146-1.101-0.234-1.658-0.234c-0.901,0-1.333,0.36-1.333,0.919c0,1.46,3.676,0.812,3.676,3.713
|
||||||
|
C112.744,20.153,111.194,21.342,108.743,21.342z M115.861,11.052c-0.793,0-1.424-0.631-1.424-1.405c0-0.757,0.631-1.389,1.424-1.389
|
||||||
|
s1.44,0.613,1.44,1.389C117.302,10.422,116.654,11.052,115.861,11.052z M114.708,21.162v-8.956h2.308v8.956H114.708z
|
||||||
|
M122.851,21.342c-1.982,0-2.613-0.721-2.613-2.811V13.99h-1.531v-1.784h1.531V9.449l2.307-0.613v3.37h2.182v1.784h-2.182v3.928
|
||||||
|
c0,1.153,0.271,1.479,1.063,1.479c0.378,0,0.793-0.055,1.117-0.145v1.856C124.147,21.252,123.481,21.342,122.851,21.342z
|
||||||
|
M131.731,21.162c0-0.521,0.019-1.045,0.091-1.514l-0.019-0.019c-0.434,1.01-1.531,1.712-2.865,1.712c-1.621,0-2.56-0.919-2.56-2.36
|
||||||
|
c0-2.145,2.126-3.279,5.172-3.279v-0.487c0-0.937-0.45-1.423-1.747-1.423c-0.812,0-1.894,0.271-2.649,0.703l-0.198-1.928
|
||||||
|
c0.901-0.324,2.056-0.56,3.208-0.56c2.884,0,3.694,1.172,3.694,3.118v3.73c0,0.721,0.018,1.567,0.054,2.307L131.731,21.162
|
||||||
|
L131.731,21.162z M128.561,10.729c-0.687,0-1.243-0.56-1.243-1.244c0-0.703,0.558-1.244,1.243-1.244
|
||||||
|
c0.685,0,1.243,0.541,1.243,1.244C129.804,10.169,129.245,10.729,128.561,10.729z M131.552,17.198c-2.433,0-2.974,0.703-2.974,1.423
|
||||||
|
c0,0.577,0.396,0.955,1.063,0.955c1.135,0,1.909-1.081,1.909-2.162L131.552,17.198L131.552,17.198z M132.2,10.729
|
||||||
|
c-0.685,0-1.243-0.56-1.243-1.244c0-0.703,0.56-1.244,1.243-1.244s1.244,0.541,1.244,1.244
|
||||||
|
C133.444,10.169,132.885,10.729,132.2,10.729z M139.55,21.342c-1.981,0-2.612-0.721-2.612-2.811V13.99h-1.531v-1.784h1.531V9.449
|
||||||
|
l2.307-0.613v3.37h2.181v1.784h-2.181v3.928c0,1.153,0.271,1.479,1.063,1.479c0.379,0,0.793-0.055,1.116-0.145v1.856
|
||||||
|
C140.847,21.252,140.181,21.342,139.55,21.342z M54.955,40.202V38.4l4.379-7.137c0.252-0.414,0.504-0.774,0.793-1.153
|
||||||
|
c-0.433,0.019-1.009,0.036-2.217,0.036h-2.811v-2.108h7.856v1.874l-4.631,7.316c-0.18,0.288-0.342,0.559-0.558,0.848
|
||||||
|
c0.306-0.036,1.135-0.036,2.631-0.036h2.631v2.162H54.955z M70.484,40.202c0-0.414,0.018-1.117,0.107-1.586l-0.018-0.018
|
||||||
|
c-0.541,1.062-1.567,1.802-3.045,1.802c-2.02,0-2.667-1.298-2.667-2.865v-6.289h2.289v5.73c0,0.937,0.252,1.496,1.117,1.496
|
||||||
|
c1.171,0,2.071-1.334,2.071-2.901v-4.325h2.308v8.956H70.484z M66.826,29.769c-0.685,0-1.243-0.56-1.243-1.244
|
||||||
|
c0-0.702,0.56-1.243,1.243-1.243c0.685,0,1.244,0.541,1.244,1.243C68.069,29.21,67.511,29.769,66.826,29.769z M70.466,29.769
|
||||||
|
c-0.685,0-1.243-0.56-1.243-1.244c0-0.702,0.559-1.243,1.243-1.243c0.686,0,1.243,0.541,1.243,1.243
|
||||||
|
C71.709,29.21,71.151,29.769,70.466,29.769z M79.926,33.318c-1.656-0.343-2.485,0.739-2.485,3.226v3.658h-2.308v-8.956h2.182
|
||||||
|
c0,0.45-0.055,1.171-0.162,1.802h0.036c0.432-1.135,1.297-2.126,2.847-2L79.926,33.318z M82.854,30.093
|
||||||
|
c-0.793,0-1.424-0.631-1.424-1.405c0-0.756,0.631-1.388,1.424-1.388s1.44,0.612,1.44,1.388
|
||||||
|
C84.295,29.462,83.646,30.093,82.854,30.093z M81.7,40.202v-8.956h2.307v8.956H81.7z M89.729,40.364
|
||||||
|
c-2.486,0-4.036-1.297-4.036-4.343c0-2.793,1.46-4.938,4.632-4.938c0.612,0,1.261,0.09,1.838,0.252l-0.233,2.001
|
||||||
|
c-0.486-0.181-1.046-0.325-1.622-0.325c-1.46,0-2.198,1.081-2.198,2.775c0,1.531,0.595,2.577,2.126,2.577
|
||||||
|
c0.612,0,1.279-0.127,1.767-0.379l0.181,1.965C91.567,40.185,90.684,40.364,89.729,40.364z M99.478,40.202v-5.729
|
||||||
|
c0-0.938-0.252-1.496-1.1-1.496c-1.172,0-2.091,1.334-2.091,2.9v4.325h-2.307V27.047h2.307v3.839c0,0.541-0.036,1.298-0.162,1.82
|
||||||
|
l0.036,0.019c0.522-1.01,1.55-1.677,2.938-1.677c2.018,0,2.667,1.299,2.667,2.865v6.289H99.478z M105.334,31.716
|
||||||
|
c-1.461,0-1.813-0.788-1.813-1.706v-2.972h1.061v2.91c0,0.537,0.17,0.877,0.822,0.877c0.599,0,0.83-0.252,0.83-0.938v-2.85h1.047
|
||||||
|
v2.788C107.279,31.118,106.552,31.716,105.334,31.716z M108.163,31.628v-0.83l1.477-2.468c0.073-0.122,0.155-0.238,0.243-0.354
|
||||||
|
c-0.12,0.007-0.277,0.014-0.721,0.014h-0.951v-0.952h2.972v0.863l-1.558,2.502c-0.055,0.089-0.107,0.164-0.177,0.259
|
||||||
|
c0.089-0.014,0.347-0.014,0.891-0.014h0.87v0.979L108.163,31.628L108.163,31.628z M114.922,31.628v-1.911h-1.68v1.911h-1.061v-4.59
|
||||||
|
h1.061V28.8h1.68v-1.762h1.062v4.59H114.922z M0,24.091C0,10.786,10.786,0,24.091,0l0,0c13.306,0,24.092,10.786,24.092,24.091l0,0
|
||||||
|
c0,13.306-10.786,24.092-24.092,24.092l0,0C10.786,48.182,0,37.396,0,24.091L0,24.091z M7.477,7.477
|
||||||
|
C3.225,11.73,0.595,17.602,0.595,24.091l0,0c0,6.489,2.629,12.361,6.882,16.614l0,0c4.253,4.252,10.125,6.881,16.613,6.881l0,0
|
||||||
|
c6.489,0,12.361-2.629,16.614-6.881l0,0c4.252-4.253,6.882-10.125,6.882-16.614l0,0c0-6.488-2.629-12.36-6.882-16.613l0,0
|
||||||
|
C36.452,3.224,30.58,0.594,24.091,0.594l0,0C17.602,0.594,11.73,3.224,7.477,7.477L7.477,7.477z M24.456,39.232h0.194v-0.34h-0.462
|
||||||
|
v0.753h0.269L24.456,39.232z M24.091,1.568c-12.436,0-22.516,10.081-22.516,22.516c0,12.437,10.081,22.518,22.516,22.518
|
||||||
|
c12.436,0,22.516-10.081,22.517-22.518C46.606,11.649,36.526,1.568,24.091,1.568z M21.598,43.19h-1.021v0.34h1.021v2.53
|
||||||
|
c-5.112-0.573-9.696-2.889-13.146-6.338c-0.495-0.495-0.967-1.015-1.414-1.555c0.091-0.549,0.565-0.967,1.141-0.967
|
||||||
|
c0.639,0,1.155,0.518,1.155,1.156v1.11h1.468v-0.007l0,0v-1.104c0-0.64,0.519-1.156,1.156-1.156c0.639,0,1.157,0.518,1.157,1.156
|
||||||
|
v1.11h1.468v-0.007l0,0v-1.104c0-0.64,0.519-1.156,1.156-1.156s1.157,0.518,1.157,1.156v1.11h1.468v-0.007l0,0v-1.104
|
||||||
|
c0-0.64,0.518-1.156,1.157-1.156c0.639,0,1.155,0.518,1.155,1.156v1.11h0.922V43.19z M25.794,46.135
|
||||||
|
c-0.562,0.044-1.13,0.065-1.703,0.065c-0.571,0-1.14-0.021-1.7-0.063l-0.418-2.606h0.481c-0.12-0.286-0.329-0.786-0.409-0.989
|
||||||
|
c-0.13-0.326-0.032-0.542,0.185-0.626c0.211-0.082,0.449,0.034,0.523,0.312l0.211,0.792h0.309v0.511l0,0v0.102h-0.729v0.341h1.066
|
||||||
|
l0.001-0.441h1.293l-0.001-0.511h0.31l0.213-0.792c0.075-0.278,0.315-0.396,0.528-0.312c0.218,0.084,0.315,0.3,0.186,0.626
|
||||||
|
c-0.035,0.089-0.093,0.235-0.154,0.396l-0.288,0.695H24.92v0.341h1.005l0.184-0.441h0.104L25.794,46.135z M23.391,38.684h1.4
|
||||||
|
c0.055,0.129,0.188,0.454,0.271,0.643c0.057,0.131,0.13,0.271,0.041,0.416c-0.106,0.171-0.245,0.146-0.342,0.139
|
||||||
|
c-0.006-0.001-0.012,0-0.018-0.001c-0.098,0.269-0.352,0.459-0.653,0.459c-0.301,0-0.555-0.19-0.652-0.459
|
||||||
|
c-0.005,0.001-0.013,0-0.018,0.001c-0.098,0.009-0.235,0.032-0.342-0.139c-0.089-0.145-0.016-0.285,0.041-0.416
|
||||||
|
C23.204,39.138,23.337,38.812,23.391,38.684z M23.18,37.23l0.447,0.641l0.458-0.869l0.458,0.869l0.448-0.641l-0.178,1.111h-1.456
|
||||||
|
L23.18,37.23z M23.715,40.376c0.105,0.293,0.385,0.504,0.715,0.504c0.356,0,0.654-0.247,0.736-0.58
|
||||||
|
c0.222,0.012,0.442,0.075,0.661,0.261c0.211,0.177,0.293,0.48,0.323,0.632h-4.116c0.029-0.15,0.112-0.455,0.323-0.632
|
||||||
|
C22.808,40.181,23.268,40.305,23.715,40.376z M25.414,41.532c-0.155,0.586-0.688,1.019-1.322,1.019
|
||||||
|
c-0.634,0-1.167-0.433-1.321-1.019H25.414z M39.729,39.723c-3.45,3.449-8.033,5.764-13.145,6.337v-2.53h0.935
|
||||||
|
c1.731,0,2.983-0.146,2.983-0.146s-1.289-0.194-2.983-0.194h-0.935v-3.721h1.117v-0.007l0,0v-1.104c0-0.64,0.519-1.156,1.157-1.156
|
||||||
|
s1.157,0.519,1.157,1.156v1.11h1.467v-0.007l0,0v-1.104c0-0.64,0.518-1.156,1.156-1.156c0.638,0,1.155,0.519,1.155,1.156v1.11h1.469
|
||||||
|
v-0.007l0,0v-1.104c0-0.64,0.518-1.156,1.156-1.156c0.64,0,1.156,0.519,1.156,1.156v1.11h1.468v-0.007l0,0v-1.104
|
||||||
|
c0-0.64,0.519-1.156,1.157-1.156c0.506,0,0.937,0.326,1.092,0.78C40.803,38.589,40.281,39.171,39.729,39.723z M41.541,37.673
|
||||||
|
c-0.257-0.541-0.808-0.916-1.445-0.916c-0.885,0-1.602,0.718-1.602,1.603v0.517h-0.579v-0.517c0-0.885-0.717-1.603-1.601-1.603
|
||||||
|
s-1.602,0.718-1.602,1.603v0.517h-0.58v-0.517c0-0.885-0.717-1.603-1.601-1.603s-1.601,0.718-1.601,1.603v0.517h-0.58v-0.517
|
||||||
|
c0-0.885-0.718-1.603-1.602-1.603s-1.601,0.718-1.601,1.603v0.517h-0.598c-0.182-1.198-1.213-2.118-2.462-2.118
|
||||||
|
s-2.279,0.92-2.462,2.118h-0.614v-0.517c0-0.885-0.718-1.603-1.602-1.603s-1.601,0.718-1.601,1.603v0.517h-0.58v-0.517
|
||||||
|
c0-0.885-0.716-1.603-1.602-1.603c-0.884,0-1.601,0.718-1.601,1.603v0.517h-0.58v-0.517c0-0.885-0.717-1.603-1.601-1.603
|
||||||
|
c-0.885,0-1.602,0.718-1.602,1.603v0.517H9.672v-0.517c0-0.885-0.717-1.603-1.601-1.603c-0.634,0-1.181,0.369-1.44,0.903
|
||||||
|
c-0.39-0.501-0.758-1.02-1.104-1.554h37.129C42.306,36.645,41.935,37.168,41.541,37.673z M43.027,35.515H5.155
|
||||||
|
c-0.11-0.183-0.217-0.366-0.322-0.553h38.517C43.243,35.148,43.137,35.333,43.027,35.515z M20.275,7.089v0.187
|
||||||
|
C20.27,7.313,20.26,7.368,20.241,7.42c-0.032,0.085-0.111,0.221-0.217,0.386c-0.04,0.064-0.11,0.174-0.188,0.33
|
||||||
|
C19.735,7.982,19.65,7.88,19.59,7.817c-0.066-0.07-0.154-0.16-0.228-0.246c-0.157-0.187-0.166-0.298-0.166-0.298l0,0
|
||||||
|
c0,0-0.005,0.11-0.163,0.297c-0.073,0.085-0.161,0.175-0.228,0.246c-0.062,0.063-0.147,0.167-0.25,0.325
|
||||||
|
c-0.08-0.161-0.151-0.272-0.192-0.341c-0.105-0.165-0.185-0.3-0.217-0.385c-0.03-0.081-0.041-0.174-0.042-0.184V7.089H20.275z
|
||||||
|
M18.109,6.749c0.017-0.277,0.092-0.805,0.362-1.164c0.204-0.278,0.407-0.443,0.557-0.54C19.096,5,19.151,4.973,19.19,4.954
|
||||||
|
c0.04,0.02,0.095,0.046,0.164,0.091c0.147,0.097,0.352,0.262,0.557,0.54c0.271,0.359,0.345,0.887,0.362,1.164H18.109z M20.354,7.988
|
||||||
|
c0.062,0.085,0.125,0.209,0.194,0.359c0.096,0.233,0.121,0.462,0.124,0.63v2.492h-0.642c0-0.548,0-1.756,0-2.491
|
||||||
|
c0.002-0.171,0.033-0.409,0.124-0.632C20.234,8.17,20.296,8.07,20.354,7.988z M19.682,8.994l-0.001,2.476h-0.974
|
||||||
|
c0-0.689-0.001-2.477-0.001-2.478c0.008-0.162,0.021-0.386,0.138-0.617c0.122-0.242,0.354-0.386,0.354-0.386h0.001
|
||||||
|
c0,0,0.219,0.144,0.342,0.386C19.664,8.618,19.675,8.828,19.682,8.994z M18.245,8.343c0.091,0.224,0.106,0.465,0.109,0.636
|
||||||
|
l0.003,2.491h-0.634V8.975c0.003-0.168,0.021-0.396,0.116-0.631c0.07-0.149,0.138-0.273,0.195-0.358
|
||||||
|
C18.106,8.091,18.175,8.193,18.245,8.343z M21.164,11.877v0.807h-3.941v-0.807H21.164z M21.164,13.022v3.141H20.21V14.75
|
||||||
|
c0.001-0.469-0.173-0.866-0.459-1.138c-0.153-0.147-0.338-0.258-0.542-0.328c-0.013-0.004-0.012-0.005-0.012-0.005
|
||||||
|
s-0.002,0-0.015,0.005c-0.204,0.07-0.39,0.181-0.543,0.328c-0.286,0.271-0.459,0.669-0.458,1.138v1.414h-0.958v-3.141L21.164,13.022
|
||||||
|
L21.164,13.022z M19.87,14.75v1.414h-1.35V14.75c0.005-0.546,0.272-0.925,0.675-1.103C19.596,13.824,19.865,14.203,19.87,14.75z
|
||||||
|
M21.164,16.503v3.995h-0.876v-1.995c0-0.468-0.176-0.875-0.47-1.155c-0.157-0.15-0.344-0.263-0.55-0.333
|
||||||
|
c-0.011-0.005-0.074-0.024-0.074-0.024s-0.062,0.02-0.067,0.022c-0.207,0.07-0.396,0.185-0.555,0.335
|
||||||
|
c-0.294,0.279-0.471,0.688-0.47,1.154v1.995h-0.88v-3.995L21.164,16.503L21.164,16.503z M19.948,18.506v1.992h-1.507v-1.995
|
||||||
|
c0-0.384,0.141-0.694,0.364-0.909c0.11-0.105,0.241-0.185,0.389-0.241h0.001c0.147,0.058,0.276,0.136,0.387,0.24
|
||||||
|
c0.226,0.215,0.364,0.525,0.365,0.91L19.948,18.506z M21.164,20.838v4.755h-3.941v-4.755H21.164z M21.164,25.933v3.103h-3.941
|
||||||
|
v-3.103H21.164z M21.164,29.375v5.247h-3.941v-5.247H21.164z M24.634,16.538v1.416l-0.542-0.542l-0.541,0.541v-1.415H24.634z
|
||||||
|
M23.566,16.13l0.396-1.694l0.163-2.835l0.098,2.833l0.396,1.696H23.566z M24.092,17.988l2.511,2.51h-5.021L24.092,17.988z
|
||||||
|
M26.603,20.838v1.921h-5.037v-1.921H26.603z M26.603,23.354v2.238h-1.575v-0.561c0-0.516-0.419-0.938-0.938-0.938
|
||||||
|
c-0.517,0-0.937,0.421-0.937,0.938v0.561h-1.589v-2.238H26.603z M23.155,25.933v1.998h1.873v-1.998h1.575v3.103h-5.037v-3.103
|
||||||
|
H23.155z M26.603,29.375v5.247h-5.037v-5.247H26.603z M30.067,7.089v0.187c-0.005,0.038-0.017,0.093-0.035,0.145
|
||||||
|
C30,7.505,29.921,7.64,29.815,7.805c-0.04,0.064-0.11,0.174-0.188,0.33c-0.101-0.153-0.186-0.256-0.246-0.318
|
||||||
|
c-0.065-0.07-0.154-0.16-0.228-0.246c-0.158-0.187-0.166-0.298-0.166-0.298l0,0c0,0-0.005,0.11-0.163,0.297
|
||||||
|
c-0.073,0.085-0.161,0.175-0.228,0.246c-0.062,0.063-0.147,0.167-0.25,0.325c-0.08-0.161-0.151-0.272-0.192-0.341
|
||||||
|
c-0.105-0.165-0.185-0.3-0.217-0.385c-0.031-0.082-0.041-0.177-0.042-0.185V7.089H30.067z M27.901,6.749
|
||||||
|
c0.017-0.277,0.092-0.805,0.362-1.164c0.204-0.278,0.407-0.443,0.557-0.54C28.888,5,28.942,4.973,28.982,4.954
|
||||||
|
c0.04,0.02,0.095,0.046,0.163,0.091c0.147,0.097,0.352,0.262,0.557,0.54c0.271,0.359,0.345,0.887,0.362,1.164H27.901z M30.146,7.988
|
||||||
|
c0.061,0.085,0.125,0.209,0.193,0.359c0.096,0.233,0.121,0.462,0.124,0.63v2.492h-0.642c0-0.548,0-1.756,0-2.491
|
||||||
|
c0.003-0.171,0.033-0.409,0.125-0.632C30.025,8.17,30.088,8.07,30.146,7.988z M29.473,8.994l-0.001,2.476H28.5
|
||||||
|
c0-0.689-0.001-2.477-0.001-2.478c0.008-0.162,0.021-0.386,0.138-0.617c0.122-0.242,0.354-0.386,0.354-0.386h0.001
|
||||||
|
c0,0,0.219,0.144,0.342,0.386C29.455,8.618,29.466,8.828,29.473,8.994z M28.036,8.343c0.091,0.224,0.106,0.465,0.109,0.636
|
||||||
|
l0.003,2.491h-0.635V8.975c0.004-0.168,0.021-0.396,0.116-0.631c0.07-0.149,0.138-0.273,0.194-0.358
|
||||||
|
C27.898,8.091,27.966,8.193,28.036,8.343z M30.956,11.877v0.807h-3.941v-0.807H30.956z M30.956,13.022v3.141h-0.954V14.75
|
||||||
|
c0-0.469-0.173-0.866-0.459-1.138c-0.153-0.147-0.339-0.258-0.543-0.328c-0.013-0.004-0.012-0.005-0.012-0.005s-0.002,0-0.015,0.005
|
||||||
|
c-0.204,0.07-0.39,0.181-0.543,0.328c-0.286,0.271-0.459,0.669-0.459,1.138v1.414h-0.958v-3.141L30.956,13.022L30.956,13.022z
|
||||||
|
M29.662,14.75v1.414h-1.351V14.75c0.005-0.546,0.272-0.925,0.675-1.103C29.388,13.824,29.657,14.203,29.662,14.75z M30.956,16.503
|
||||||
|
v3.995H30.08v-1.995c0-0.468-0.176-0.875-0.47-1.155c-0.157-0.15-0.344-0.263-0.55-0.333c-0.01-0.005-0.074-0.024-0.074-0.024
|
||||||
|
s-0.062,0.02-0.068,0.022c-0.207,0.07-0.396,0.185-0.555,0.335c-0.294,0.279-0.47,0.688-0.47,1.154v1.995h-0.88v-3.995
|
||||||
|
L30.956,16.503L30.956,16.503z M29.74,18.506v1.992h-1.506v-1.995c0-0.384,0.141-0.694,0.364-0.909
|
||||||
|
c0.11-0.105,0.241-0.185,0.388-0.241h0.001c0.147,0.058,0.277,0.136,0.388,0.24c0.225,0.215,0.364,0.525,0.365,0.91V18.506z
|
||||||
|
M30.956,20.838v4.755h-3.941v-4.755H30.956z M30.956,25.933v3.103h-3.941v-3.103H30.956z M30.956,29.375v5.247h-3.941v-5.247
|
||||||
|
H30.956z M31.562,34.622V11.469h-0.497V8.917c-0.005-0.317-0.051-0.519-0.191-0.844c-0.036-0.082-0.087-0.172-0.145-0.262V6.889
|
||||||
|
c0,0-0.001-0.725-0.3-1.27c-0.325-0.595-0.956-0.92-1.264-1.049c-0.07-0.033-0.117-0.048-0.126-0.05l-0.051-0.019l-0.063,0.019
|
||||||
|
c-0.03,0.009-0.529,0.167-1.004,0.812c-0.43,0.593-0.444,1.354-0.448,1.563c0,0.034,0.001,0.054,0.001,0.057v0.851
|
||||||
|
c-0.058,0.084-0.138,0.211-0.226,0.398c-0.132,0.324-0.141,0.624-0.146,0.804v2.465h-0.5v8.452l-1.368-1.367v-2.413l-0.464-1.558
|
||||||
|
l-0.68-5.341l0,0l-0.501,5.117l-0.466,1.782v2.234l-1.354,1.355v-8.265h-0.497V8.917c-0.005-0.317-0.051-0.519-0.192-0.844
|
||||||
|
c-0.035-0.082-0.087-0.172-0.144-0.262V6.889c0,0-0.001-0.725-0.3-1.27c-0.326-0.595-0.957-0.92-1.264-1.049
|
||||||
|
c-0.07-0.033-0.117-0.048-0.126-0.05l-0.051-0.019l-0.063,0.019c-0.031,0.009-0.529,0.167-1.005,0.812
|
||||||
|
c-0.43,0.593-0.444,1.354-0.448,1.563c0,0.034,0,0.054,0,0.057v0.851c-0.058,0.084-0.138,0.211-0.226,0.398
|
||||||
|
c-0.131,0.324-0.141,0.624-0.145,0.804v2.465h-0.5v23.151H4.646c-1.702-3.133-2.672-6.721-2.672-10.538
|
||||||
|
c0-6.106,2.475-11.635,6.477-15.639c4.003-4.002,9.531-6.479,15.639-6.479c6.108,0,11.637,2.476,15.64,6.479
|
||||||
|
c4.002,4.003,6.478,9.531,6.478,15.639c0,3.817-0.97,7.405-2.672,10.538L31.562,34.622L31.562,34.622z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 53 KiB |
BIN
static/images/wait.gif
Normal file
|
After Width: | Height: | Size: 814 B |
1782
static/js/d3-pathway.js
vendored
Normal file
217
static/js/epp/epp.js
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
class Setting {
|
||||||
|
constructor(nameInputId, selectedPackagesId, relativeReasoningSelectId, cutoffInputId, evaluationTypeSelectId,
|
||||||
|
availableTSSelectId, formsId, tableId, summaryTableId) {
|
||||||
|
this.nameInputId = nameInputId;
|
||||||
|
this.selectedPackagesId = selectedPackagesId;
|
||||||
|
this.relativeReasoningSelectId = relativeReasoningSelectId;
|
||||||
|
this.cutoffInputId = cutoffInputId;
|
||||||
|
this.evaluationTypeSelectId = evaluationTypeSelectId;
|
||||||
|
this.availableTSSelectId = availableTSSelectId;
|
||||||
|
this.formsId = formsId;
|
||||||
|
this.tableId = tableId;
|
||||||
|
this.summaryTableId = summaryTableId;
|
||||||
|
|
||||||
|
// General settings
|
||||||
|
this.name = null;
|
||||||
|
this.selectedPackages = [];
|
||||||
|
|
||||||
|
// Relative Reasoning related
|
||||||
|
this.selectedRelativeReasoning = null;
|
||||||
|
this.cutoff = null;
|
||||||
|
this.evaluationType = null;
|
||||||
|
|
||||||
|
// parameters such as { "lowPH": 7, "highPH": 8 }
|
||||||
|
this.tsParams = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
extractName() {
|
||||||
|
var tempName = $('#' + this.nameInputId).val()
|
||||||
|
if (tempName == '') {
|
||||||
|
console.log("Name was empty...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.name = tempName;
|
||||||
|
}
|
||||||
|
|
||||||
|
extractSelectedPackages() {
|
||||||
|
var selPacks = $("#" + this.selectedPackagesId + " :selected");
|
||||||
|
var ref = this;
|
||||||
|
ref.selectedPackages = [];
|
||||||
|
selPacks.each(function () {
|
||||||
|
var obj = {}
|
||||||
|
obj['id'] = this.value;
|
||||||
|
obj['name'] = this.text;
|
||||||
|
ref.selectedPackages.push(obj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
extractRelativeReasoning() {
|
||||||
|
var tempRR = $('#' + this.relativeReasoningSelectId + " :selected").val()
|
||||||
|
if (tempRR == '') {
|
||||||
|
console.log("RR was empty...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var obj = {}
|
||||||
|
obj['id'] = $('#' + this.relativeReasoningSelectId + " :selected").val()
|
||||||
|
obj['name'] = $('#' + this.relativeReasoningSelectId + " :selected").text()
|
||||||
|
this.selectedRelativeReasoning = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
extractCutoff() {
|
||||||
|
var tempCutoff = $('#' + this.cutoffInputId).val()
|
||||||
|
if (tempCutoff == '') {
|
||||||
|
console.log("Cutoff was empty...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.cutoff = tempCutoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
extractEvaluationType() {
|
||||||
|
var tempEvaluationType = $('#' + this.evaluationTypeSelectId).val()
|
||||||
|
if (tempEvaluationType == '') {
|
||||||
|
console.log("EvaluationType was empty...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.evaluationType = tempEvaluationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
addTruncator() {
|
||||||
|
// triggered by "Add"
|
||||||
|
// will extract values and afterwards updates table + summary
|
||||||
|
var type = $("#" + this.availableTSSelectId + " :selected").val();
|
||||||
|
var text = $("#" + this.availableTSSelectId + " :selected").text();
|
||||||
|
var form = $("#" + type + "_form > :input")
|
||||||
|
|
||||||
|
// flag to check whether at least one input had a valid value
|
||||||
|
var addedValue = false;
|
||||||
|
|
||||||
|
// reference being used in each
|
||||||
|
var ref = this;
|
||||||
|
|
||||||
|
form.each(function() {
|
||||||
|
if(this.value == "" || this.value === "undefined"){
|
||||||
|
console.log(this);
|
||||||
|
console.log("Skipping " + this.name);
|
||||||
|
} else {
|
||||||
|
var obj = {}
|
||||||
|
obj[this.name] = this.value;
|
||||||
|
obj['text'] = text;
|
||||||
|
ref.tsParams[type] = obj
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateTable();
|
||||||
|
this.updateSummaryTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeTruncator(rowId) {
|
||||||
|
var summary = rowId.startsWith("sum") ? true : false;
|
||||||
|
// plain key
|
||||||
|
var key = rowId.replace(summary ? "sum" : "trunc", "").replace("row", "");
|
||||||
|
|
||||||
|
console.log("Removing " + key);
|
||||||
|
|
||||||
|
// remove the rows
|
||||||
|
$("#trunc"+ key + "row").remove();
|
||||||
|
if($("#sum"+ key + "row").length > 0) {
|
||||||
|
$("#sum"+ key + "row").remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete this.tsParams[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTable() {
|
||||||
|
// remove all children
|
||||||
|
$('#'+this.tableId + "Body").empty()
|
||||||
|
|
||||||
|
var innerHTML = "<tr>" +
|
||||||
|
"<td>Name</td>" +
|
||||||
|
"<td>Value</td>" +
|
||||||
|
"<td width='10%'>Action</td>" +
|
||||||
|
"</tr>";
|
||||||
|
|
||||||
|
for (var x in this.tsParams) {
|
||||||
|
var val = "";
|
||||||
|
for (var y in this.tsParams[x]){
|
||||||
|
if (y == 'text') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
val += this.tsParams[x][y]
|
||||||
|
|
||||||
|
}
|
||||||
|
innerHTML += "<tr id='trunc" + x + "row'>" +
|
||||||
|
"<td>" + this.tsParams[x]['text'] + "</td>" +
|
||||||
|
"<td>" + val + "</td>" +
|
||||||
|
"<td width='10%'>"+
|
||||||
|
"<button type='button' id='" + x + "button' class='form-control' onclick='s.removeTruncator(\"trunc" + x + "row\")'>Remove</button>" +
|
||||||
|
"</td>" +
|
||||||
|
"</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#'+this.tableId + "Body").append(innerHTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
packageRows() {
|
||||||
|
var res = '';
|
||||||
|
for(var p in this.selectedPackages) {
|
||||||
|
var obj = this.selectedPackages[p];
|
||||||
|
res += "<tr>" +
|
||||||
|
"<td>Package</td>" +
|
||||||
|
"<td>" + obj['name'] + "</td>" +
|
||||||
|
"<td width='10%'>" +
|
||||||
|
// "<button type='button' id='relativereasoningbutton' class='form-control' onclick='s.removeTruncator(\"Relative Reasoning\")'>Remove</button>" +
|
||||||
|
"</td>" +
|
||||||
|
"</tr>";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
modelRow() {
|
||||||
|
if(this.selectedRelativeReasoning == null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return "<tr>" +
|
||||||
|
"<td>Relative Reasoning</td>" +
|
||||||
|
"<td>" + this.selectedRelativeReasoning['name'] + " " + (this.evaluationType == "singleGen" ? "SG" : "MG") + " with t=" + this.cutoff + " </td>" +
|
||||||
|
"<td width='10%'>" +
|
||||||
|
// "<button type='button' id='relativereasoningbutton' class='form-control' onclick='s.removeTruncator(\"Relative Reasoning\")'>Remove</button>" +
|
||||||
|
"</td>" +
|
||||||
|
"</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSummaryTable() {
|
||||||
|
// remove all children
|
||||||
|
$('#'+this.summaryTableId + "Body").empty()
|
||||||
|
|
||||||
|
var innerHTML = "<tr>" +
|
||||||
|
"<td>Name</td>" +
|
||||||
|
"<td>Value</td>" +
|
||||||
|
"<td width='10%'>Action</td>" +
|
||||||
|
"</tr>";
|
||||||
|
|
||||||
|
innerHTML += this.packageRows();
|
||||||
|
innerHTML += this.modelRow();
|
||||||
|
|
||||||
|
// var innerHTML = ''
|
||||||
|
for (var x in this.tsParams) {
|
||||||
|
var val = "";
|
||||||
|
for (var y in this.tsParams[x]){
|
||||||
|
if (y == 'text') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
val += this.tsParams[x][y]
|
||||||
|
|
||||||
|
}
|
||||||
|
innerHTML += "<tr id='sum" + x + "row'>" +
|
||||||
|
"<td>" + this.tsParams[x]['text'] + "</td>" +
|
||||||
|
"<td>" + val + "</td>" +
|
||||||
|
"<td width='10%'>"+
|
||||||
|
"<button type='button' id='" + x + "button' class='form-control' onclick='s.removeTruncator(\"sum" + x + "row\")'>Remove</button>" +
|
||||||
|
"</td>" +
|
||||||
|
"</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#'+this.summaryTableId + "Body").append(innerHTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1
static/js/epp/jquery-bootstrap-modal-steps.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!function(t){"use strict";t.fn.modalSteps=function(a){var e=this,n=t.extend({btnCancelHtml:"Cancel",btnPreviousHtml:"Previous",btnNextHtml:"Next",btnLastStepHtml:"Complete",disableNextButton:!1,completeCallback:function(){},callbacks:{},getTitleAndStep:function(){}},a),d=function(t){return void 0!==t&&"function"==typeof t&&(t(),!0)};return e.on("show.bs.modal",function(){var a,l,s,i=e.find(".modal-footer"),o=i.find(".js-btn-step[data-orientation=cancel]"),p=i.find(".js-btn-step[data-orientation=previous]"),r=i.find(".js-btn-step[data-orientation=next]"),c=n.callbacks["*"],b=n.callbacks[1];n.disableNextButton&&r.attr("disabled","disabled"),p.attr("disabled","disabled"),function(){var t=n.callbacks["*"];if(void 0!==t&&"function"!=typeof t)throw"everyStepCallback is not a function! I need a function";if("function"!=typeof n.completeCallback)throw"completeCallback is not a function! I need a function";for(var a in n.callbacks)if(n.callbacks.hasOwnProperty(a)){var e=n.callbacks[a];if("*"!==a&&void 0!==e&&"function"!=typeof e)throw"Step "+a+" callback must be a function"}}(),d(c),d(b),o.html(n.btnCancelHtml),p.html(n.btnPreviousHtml),r.html(n.btnNextHtml),a=t("<input>").attr({type:"hidden",id:"actual-step",value:"1"}),e.find("#actual-step").remove(),e.append(a),e.find("[data-step=1]").removeClass("d-none"),r.attr("data-step",2),l=e.find("[data-step=1]").data("title"),s=t("<span>").addClass("label label-success").html(1),e.find(".js-title-step").append(s).append(" "+l),n.getTitleAndStep(a.attr("data-title"),1)}).on("hidden.bs.modal",function(){var t=e.find("#actual-step"),a=e.find(".js-btn-step[data-orientation=next]");e.find("[data-step]").not(e.find(".js-btn-step")).addClass("d-none"),t.not(e.find(".js-btn-step")).remove(),a.attr("data-step",1).html(n.btnNextHtml),e.find(".js-title-step").html("")}),e.find(".js-btn-step").on("click",function(){var a,l,s,i,o=t(this),p=e.find("#actual-step"),r=e.find(".js-btn-step[data-orientation=previous]"),c=e.find(".js-btn-step[data-orientation=next]"),b=e.find(".js-title-step"),f=o.data("orientation"),u=parseInt(p.val()),m=n.callbacks["*"];if(a=e.find("div[data-step]").length,"complete"===o.attr("data-step"))return n.completeCallback(),void e.modal("hide");if("next"===f)l=u+1,r.attr("data-step",u),p.val(l);else{if("previous"!==f)return void e.modal("hide");l=u-1,c.attr("data-step",u),r.attr("data-step",l-1),p.val(u-1)}parseInt(p.val())===a?c.attr("data-step","complete").html(n.btnLastStepHtml):c.attr("data-step",l).html(n.btnNextHtml),n.disableNextButton&&c.attr("disabled","disabled"),e.find("[data-step="+u+"]").not(e.find(".js-btn-step")).addClass("d-none"),e.find("[data-step="+l+"]").not(e.find(".js-btn-step")).removeClass("d-none"),parseInt(r.attr("data-step"))>0?r.removeAttr("disabled"):r.attr("disabled","disabled"),"previous"===f&&c.removeAttr("disabled"),(s=e.find("[data-step="+l+"]")).attr("data-unlock-continue")&&c.removeAttr("disabled"),i=s.attr("data-title");var v=t("<span>").addClass("label label-success").html(l);b.html(v).append(" "+i),n.getTitleAndStep(s.attr("data-title"),l);var h=n.callbacks[p.val()];d(m),d(h)}),this}}(jQuery);
|
||||||
191
static/js/epp/pathway.js
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
// drawarea
|
||||||
|
var svg;
|
||||||
|
|
||||||
|
// colors
|
||||||
|
var border = "thin solid lightgrey";
|
||||||
|
|
||||||
|
|
||||||
|
// nodes
|
||||||
|
|
||||||
|
|
||||||
|
// links
|
||||||
|
|
||||||
|
// tree
|
||||||
|
var compoundSize = 75; // = diameter of nodes of small compounds
|
||||||
|
var maxCompoundSize = function(){ return 1.5 * compoundSize }; // limit increased size of larger compounds
|
||||||
|
var maxCompoundPopupSize = function(){ return 5 * compoundSize };
|
||||||
|
var compoundImageMargin = 0.15; // compounds images are rectangles, reduce size to fit into nodes
|
||||||
|
|
||||||
|
var treeLayoutLinkDistance = function(){ return 2.5 * compoundSize };
|
||||||
|
var treeLayoutCharge = -1000; // compounds push each other apart
|
||||||
|
var treeLayoutPseudoCharge = treeLayoutCharge * 0.1; // relaxes forces on pseudo nodes
|
||||||
|
var treeLayoutLevelGravity = 0.5; // pulls compounds back to their depth level
|
||||||
|
var treeLayoutXCenterGravity = 0.03; // pulls compounds to x center
|
||||||
|
var treeLayoutLevels = function(){ return treeLayoutLinkDistance() }; // distance between depth levels
|
||||||
|
var treeLayoutXInitMargin = function(){ return treeLayoutLinkDistance() }; // initial x-distance between nodes of same depth
|
||||||
|
|
||||||
|
|
||||||
|
// Convenience method to check wether a given node is a leaf
|
||||||
|
function isLeaf(node) {
|
||||||
|
return node.children.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMaxNodeDepth(graph) {
|
||||||
|
maxDepth = 0
|
||||||
|
graph.nodes.forEach(function(node, i) {
|
||||||
|
if (node.depth > maxDepth)
|
||||||
|
maxDepth = node.depth;
|
||||||
|
});
|
||||||
|
return maxDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds a parents[] and a children[] array for each node set treeSize
|
||||||
|
function setChildrenAndParents(graph) {
|
||||||
|
// Init arrays on each node
|
||||||
|
graph.nodes.forEach(function(node, i) {
|
||||||
|
node.parents = []
|
||||||
|
node.children = []
|
||||||
|
});
|
||||||
|
|
||||||
|
// loop through links, determine source and target and populate
|
||||||
|
// their parent/children arrays
|
||||||
|
graph.links.forEach(function(link, j) {
|
||||||
|
source = graph.nodes[link.source];
|
||||||
|
target = graph.nodes[link.target];
|
||||||
|
source.children.push(target);
|
||||||
|
target.parents.push(source);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Recursively traverses the tree to count the nodes that can be reached
|
||||||
|
function count(node) {
|
||||||
|
node.touch = true;
|
||||||
|
c = 1;
|
||||||
|
node.children.forEach(function(child, i) {
|
||||||
|
if (!child.touch) {
|
||||||
|
c += count(child);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
node.count = false;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check how many nodes can be reached from each given node
|
||||||
|
// by traversing the children property
|
||||||
|
graph.nodes.forEach(function(node, i) {
|
||||||
|
// reset touch on all nodes
|
||||||
|
graph.nodes.forEach(function(n, i) {
|
||||||
|
n.touch = false;
|
||||||
|
});
|
||||||
|
// get count
|
||||||
|
node.downstreamNodeCount = count(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
// determine siblings for each links
|
||||||
|
graph.links.forEach(function(link, j) {
|
||||||
|
p = graph.nodes[link.source].children.length;
|
||||||
|
c = graph.nodes[link.target].parents.length;
|
||||||
|
link.siblings = Math.max(p, c);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets all links to pseudo that are connected to a pseudo node
|
||||||
|
function setPseudoLinks(graph) {
|
||||||
|
graph.links.forEach(function(link, j) {
|
||||||
|
if (graph.nodes[link.source].pseudo || graph.nodes[link.target].pseudo) {
|
||||||
|
link.pseudo = true;
|
||||||
|
} else {
|
||||||
|
link.pseudo = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function redraw() {
|
||||||
|
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
// remove all;
|
||||||
|
svg.selectAll("g.node").remove();
|
||||||
|
svg.selectAll("rect").remove();
|
||||||
|
svg.selectAll("image").remove();
|
||||||
|
svg.selectAll("line").remove();
|
||||||
|
svg.selectAll("marker").remove();
|
||||||
|
svg.selectAll("text").remove();
|
||||||
|
svg.selectAll("g").remove();
|
||||||
|
svg.selectAll("defs").remove();
|
||||||
|
//start(__graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _drawPathway(elem, graph, options) {
|
||||||
|
width = document.getElementById(elem).offsetWidth;
|
||||||
|
height = width * 0.75;
|
||||||
|
|
||||||
|
svg = d3.select("#" + elem)
|
||||||
|
.append("svg")
|
||||||
|
.attr("width", "100%")
|
||||||
|
.attr("height", height)
|
||||||
|
.style("border", border)
|
||||||
|
.attr("inline", "block")
|
||||||
|
.attr("margin", "auto")
|
||||||
|
.attr("pointer-events", "all")
|
||||||
|
.append('svg:g')
|
||||||
|
.call(d3.behavior.zoom().on("zoom", redraw))
|
||||||
|
.attr("preserveAspectRatio", "xMidYMid meet")
|
||||||
|
.append('svg:g');
|
||||||
|
|
||||||
|
// Background rectangle to enable zoom function
|
||||||
|
// even cursor is not on a node or path
|
||||||
|
svg.append('svg:rect')
|
||||||
|
.attr('width', 9 * width)
|
||||||
|
.attr('height', 9 * height)
|
||||||
|
.attr('fill', 'white')
|
||||||
|
.attr("x", -4 * width)
|
||||||
|
.attr("y", -4 * height)
|
||||||
|
.attr("opacity", 0.0);
|
||||||
|
|
||||||
|
setChildrenAndParents(graph)
|
||||||
|
setPseudoLinks(graph)
|
||||||
|
var maxDepths = getMaxNodeDepth(graph);
|
||||||
|
|
||||||
|
// if(options.treeLayout) {
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
force = d3.layout.force()
|
||||||
|
.charge(function(d) {
|
||||||
|
if (d.pseudo) {
|
||||||
|
return treeLayoutPseudoCharge;
|
||||||
|
} else {
|
||||||
|
return treeLayoutCharge;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.gravity(0)
|
||||||
|
.linkDistance(function(d) {
|
||||||
|
dist = Math.abs(d.target.treeLevel - d.source.treeLevel) * treeLayoutLinkDistance();
|
||||||
|
if (dist == 0) {
|
||||||
|
// nodes with depth in brackets: A (0) -> B (1) + C (2)
|
||||||
|
// then there is a pseudo node that is on the same level as B
|
||||||
|
dist = 0.5 * treeLayoutLinkDistance();
|
||||||
|
}
|
||||||
|
return dist;
|
||||||
|
})
|
||||||
|
.linkStrength(function(d) {
|
||||||
|
return strength = 1 / d.siblings;
|
||||||
|
})
|
||||||
|
.size([width, height]);
|
||||||
|
|
||||||
|
force.nodes(graph.nodes).links(graph.links).start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPathway(elem, options) {
|
||||||
|
|
||||||
|
d3.json("", function(error, graph) {
|
||||||
|
if (graph) {
|
||||||
|
_drawPathway(elem, graph, options);
|
||||||
|
} else {
|
||||||
|
throw new Error("Graph not defined: " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
228
static/js/jquery-bootstrap-modal-steps.js
vendored
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/* global jQuery */
|
||||||
|
|
||||||
|
(function($){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$.fn.modalSteps = function(options){
|
||||||
|
var $modal = this;
|
||||||
|
|
||||||
|
var settings = $.extend({
|
||||||
|
btnCancelHtml: 'Cancel',
|
||||||
|
btnPreviousHtml: 'Previous',
|
||||||
|
btnNextHtml: 'Next',
|
||||||
|
btnLastStepHtml: 'Complete',
|
||||||
|
disableNextButton: false,
|
||||||
|
completeCallback: function(){},
|
||||||
|
callbacks: {}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
|
||||||
|
var validCallbacks = function(){
|
||||||
|
var everyStepCallback = settings.callbacks['*'];
|
||||||
|
|
||||||
|
if (everyStepCallback !== undefined && typeof(everyStepCallback) !== 'function'){
|
||||||
|
throw 'everyStepCallback is not a function! I need a function';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(settings.completeCallback) !== 'function') {
|
||||||
|
throw 'completeCallback is not a function! I need a function';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var step in settings.callbacks){
|
||||||
|
if (settings.callbacks.hasOwnProperty(step)){
|
||||||
|
var callback = settings.callbacks[step];
|
||||||
|
|
||||||
|
if (step !== '*' && callback !== undefined && typeof(callback) !== 'function'){
|
||||||
|
throw 'Step ' + step + ' callback must be a function';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var executeCallback = function(callback){
|
||||||
|
if (callback !== undefined && typeof(callback) === 'function'){
|
||||||
|
callback();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$modal
|
||||||
|
.on('show.bs.modal', function(){
|
||||||
|
var $modalFooter = $modal.find('.modal-footer'),
|
||||||
|
$btnCancel = $modalFooter.find('.js-btn-step[data-orientation=cancel]'),
|
||||||
|
$btnPrevious = $modalFooter.find('.js-btn-step[data-orientation=previous]'),
|
||||||
|
$btnNext = $modalFooter.find('.js-btn-step[data-orientation=next]'),
|
||||||
|
everyStepCallback = settings.callbacks['*'],
|
||||||
|
stepCallback = settings.callbacks['1'],
|
||||||
|
actualStep,
|
||||||
|
$actualStep,
|
||||||
|
titleStep,
|
||||||
|
$titleStepSpan,
|
||||||
|
nextStep;
|
||||||
|
|
||||||
|
if (settings.disableNextButton){
|
||||||
|
$btnNext.attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
$btnPrevious.attr('disabled', 'disabled');
|
||||||
|
|
||||||
|
validCallbacks();
|
||||||
|
executeCallback(everyStepCallback);
|
||||||
|
executeCallback(stepCallback);
|
||||||
|
|
||||||
|
// Setting buttons
|
||||||
|
$btnCancel.html(settings.btnCancelHtml);
|
||||||
|
$btnPrevious.html(settings.btnPreviousHtml);
|
||||||
|
$btnNext.html(settings.btnNextHtml);
|
||||||
|
|
||||||
|
$actualStep = $('<input>').attr({
|
||||||
|
'type': 'hidden',
|
||||||
|
'id': 'actual-step',
|
||||||
|
'value': '1',
|
||||||
|
});
|
||||||
|
|
||||||
|
$modal.find('#actual-step').remove();
|
||||||
|
$modal.append($actualStep);
|
||||||
|
|
||||||
|
actualStep = 1;
|
||||||
|
nextStep = actualStep + 1;
|
||||||
|
|
||||||
|
$modal.find('[data-step=' + actualStep + ']').removeClass('hide');
|
||||||
|
$btnNext.attr('data-step', nextStep);
|
||||||
|
|
||||||
|
titleStep = $modal.find('[data-step=' + actualStep + ']').data('title');
|
||||||
|
$titleStepSpan = $('<span>')
|
||||||
|
.addClass('label label-success')
|
||||||
|
.html(actualStep);
|
||||||
|
|
||||||
|
$modal
|
||||||
|
.find('.js-title-step')
|
||||||
|
.append($titleStepSpan)
|
||||||
|
.append(' ' + titleStep);
|
||||||
|
})
|
||||||
|
.on('hidden.bs.modal', function(){
|
||||||
|
var $actualStep = $modal.find('#actual-step'),
|
||||||
|
$btnNext = $modal.find('.js-btn-step[data-orientation=next]');
|
||||||
|
|
||||||
|
$modal
|
||||||
|
.find('[data-step]')
|
||||||
|
.not($modal.find('.js-btn-step'))
|
||||||
|
.addClass('hide');
|
||||||
|
|
||||||
|
$actualStep
|
||||||
|
.not($modal.find('.js-btn-step'))
|
||||||
|
.remove();
|
||||||
|
|
||||||
|
$btnNext
|
||||||
|
.attr('data-step', 1)
|
||||||
|
.html(settings.btnNextHtml);
|
||||||
|
|
||||||
|
$modal.find('.js-title-step').html('');
|
||||||
|
});
|
||||||
|
|
||||||
|
$modal.find('.js-btn-step').on('click', function(){
|
||||||
|
var $btn = $(this),
|
||||||
|
$actualStep = $modal.find('#actual-step'),
|
||||||
|
$btnPrevious = $modal.find('.js-btn-step[data-orientation=previous]'),
|
||||||
|
$btnNext = $modal.find('.js-btn-step[data-orientation=next]'),
|
||||||
|
$title = $modal.find('.js-title-step'),
|
||||||
|
orientation = $btn.data('orientation'),
|
||||||
|
actualStep = parseInt($actualStep.val()),
|
||||||
|
everyStepCallback = settings.callbacks['*'],
|
||||||
|
steps,
|
||||||
|
nextStep,
|
||||||
|
$nextStep,
|
||||||
|
newTitle;
|
||||||
|
|
||||||
|
steps = $modal.find('div[data-step]').length;
|
||||||
|
|
||||||
|
// Callback on Complete
|
||||||
|
if ($btn.attr('data-step') === 'complete'){
|
||||||
|
settings.completeCallback();
|
||||||
|
$modal.modal('hide');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the orientation to make logical operations with actualStep/nextStep
|
||||||
|
if (orientation === 'next'){
|
||||||
|
nextStep = actualStep + 1;
|
||||||
|
|
||||||
|
$btnPrevious.attr('data-step', actualStep);
|
||||||
|
$actualStep.val(nextStep);
|
||||||
|
|
||||||
|
} else if (orientation === 'previous'){
|
||||||
|
nextStep = actualStep - 1;
|
||||||
|
|
||||||
|
$btnNext.attr('data-step', actualStep);
|
||||||
|
$btnPrevious.attr('data-step', nextStep - 1);
|
||||||
|
|
||||||
|
$actualStep.val(actualStep - 1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$modal.modal('hide');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseInt($actualStep.val()) === steps){
|
||||||
|
$btnNext
|
||||||
|
.attr('data-step', 'complete')
|
||||||
|
.html(settings.btnLastStepHtml);
|
||||||
|
} else {
|
||||||
|
$btnNext
|
||||||
|
.attr('data-step', nextStep)
|
||||||
|
.html(settings.btnNextHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.disableNextButton){
|
||||||
|
$btnNext.attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide and Show steps
|
||||||
|
$modal
|
||||||
|
.find('[data-step=' + actualStep + ']')
|
||||||
|
.not($modal.find('.js-btn-step'))
|
||||||
|
.addClass('hide');
|
||||||
|
|
||||||
|
$modal
|
||||||
|
.find('[data-step=' + nextStep + ']')
|
||||||
|
.not($modal.find('.js-btn-step'))
|
||||||
|
.removeClass('hide');
|
||||||
|
|
||||||
|
// Just a check for the class of previous button
|
||||||
|
if (parseInt($btnPrevious.attr('data-step')) > 0 ){
|
||||||
|
$btnPrevious.removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
$btnPrevious.attr('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orientation === 'previous'){
|
||||||
|
$btnNext.removeAttr('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next step
|
||||||
|
$nextStep = $modal.find('[data-step=' + nextStep + ']');
|
||||||
|
|
||||||
|
// Verify if we need to unlock continue btn of the next step
|
||||||
|
if ($nextStep.attr('data-unlock-continue')){
|
||||||
|
$btnNext.removeAttr('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the title of step
|
||||||
|
newTitle = $nextStep.attr('data-title');
|
||||||
|
var $titleStepSpan = $('<span>')
|
||||||
|
.addClass('label label-success')
|
||||||
|
.html(nextStep);
|
||||||
|
|
||||||
|
$title
|
||||||
|
.html($titleStepSpan)
|
||||||
|
.append(' ' + newTitle);
|
||||||
|
|
||||||
|
var stepCallback = settings.callbacks[$actualStep.val()];
|
||||||
|
executeCallback(everyStepCallback);
|
||||||
|
executeCallback(stepCallback);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
}(jQuery));
|
||||||
57
static/js/ketcher2/DEVNOTES.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Stable [Node.js](https://nodejs.org) version
|
||||||
|
|
||||||
|
## Build instructions
|
||||||
|
|
||||||
|
npm install
|
||||||
|
npm start
|
||||||
|
|
||||||
|
For production build:
|
||||||
|
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
You could also build only the style with command
|
||||||
|
|
||||||
|
npm run style
|
||||||
|
|
||||||
|
## Indigo Service
|
||||||
|
|
||||||
|
Ketcher uses Indigo Service for server operations.
|
||||||
|
You can use `--api-path` parameter to start with it:
|
||||||
|
|
||||||
|
npm start -- --api-path=<server-url>
|
||||||
|
For production build:
|
||||||
|
|
||||||
|
npm run build -- --api-path=<server-url>
|
||||||
|
|
||||||
|
You can find the instruction for service installation
|
||||||
|
[here](http://lifescience.opensource.epam.com/indigo/service/index.html).
|
||||||
|
|
||||||
|
## Tests instructions
|
||||||
|
|
||||||
|
You can start tests for input/output `.mol`-files and render.
|
||||||
|
|
||||||
|
npm test
|
||||||
|
|
||||||
|
Tests are started for all structures in `test/fixtures` directory.
|
||||||
|
|
||||||
|
To start the tests separately:
|
||||||
|
|
||||||
|
npm run test-io
|
||||||
|
npm run test-render
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
You can use following parameters to start the tests:
|
||||||
|
- `--fixtures` - for the choice of a specific directory with molecules
|
||||||
|
- `--headless` - for start of the browser in headless mode
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run test-render -- --fixtures=fixtures/super --headless
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have added new structures for testing to the `test/fixtures` directory
|
||||||
|
you have to generate `svg` from them for correct render-test with:
|
||||||
|
|
||||||
|
npm run generate-svg
|
||||||
184
static/js/ketcher2/LICENSE
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2017 EPAM Systems
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
5
static/js/ketcher2/LICENSE-history
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Ketcher version 1 was released under GNU Affero General Public License v3.0
|
||||||
|
Ketcher version 2 was re-licensed under Apache License, Version 2.
|
||||||
|
|
||||||
|
Current version is distributed by the terms of the Apache License, Version 2.
|
||||||
|
which is included in the file LICENSE, found at the root of the Ketcher source tree.
|
||||||
19
static/js/ketcher2/NOTICE
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Ketcher
|
||||||
|
Copyright (C) 2017 EPAM Systems
|
||||||
|
This product includes software developed at EPAM Systems, Inc.
|
||||||
|
|
||||||
|
In addition, this product contains dependencies on files licensed under:
|
||||||
|
|
||||||
|
The FreeBSD Documentation License https://www.freebsd.org/copyright/freebsd-doc-license.html
|
||||||
|
The MIT License https://opensource.org/licenses/MIT
|
||||||
|
X11 License http://www.xfree86.org/3.3.6/COPYRIGHT2.html
|
||||||
|
Academic Free License https://opensource.org/licenses/AFL-3.0
|
||||||
|
Apache License, Version 1.0 http://www.apache.org/licenses/LICENSE-1.0
|
||||||
|
Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
The 2-Clause BSD License https://opensource.org/licenses/BSD-2-Clause
|
||||||
|
The 3-Clause BSD License https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
ISC License (ISC) https://opensource.org/licenses/ISC
|
||||||
|
GNU Lesser General Public License version 2.1 https://opensource.org/licenses/LGPL-2.1
|
||||||
|
The Mozilla Public License https://opensource.org/licenses/MPL-1.0
|
||||||
|
Public Domain https://wiki.creativecommons.org/wiki/Public_domain
|
||||||
|
Unlicense http://unlicense.org/
|
||||||