Commit 0fe32489 authored by Fabien  MAREUIL's avatar Fabien MAREUIL
Browse files

merge with master

parents 773cb7d5 3fa27ed6
Pipeline #46729 failed with stages
in 13 minutes and 59 seconds
......@@ -5,6 +5,8 @@
venv
ippisite/docs/build
ippisite/docs/source/_autosummary
ippisite/docs/source/ippidb
ippisite/docs/source/ippisite
/ippidb_backend/PrepareFingerPrints/nbproject/private/
/ippidb_backend/PrepareFingerPrints/build/
/ippidb_backend/PrepareFingerPrints/dist/
......
......@@ -62,7 +62,7 @@ test-centos7:
- coverage html
- pip3.6 install sphinx sphinx-argparse sphinxcontrib.bibtex sphinx_rtd_theme
- cd docs
- make html
- PYTHON=python3.6 make html
artifacts:
paths:
- ippisite/htmlcov
......
......@@ -5,11 +5,10 @@ CELERYD_CHDIR="/home/ippidb/ippidb-web-{{ http_port }}/ippisite"
CELERYD_OPTS="--time-limit=172800 --concurrency=1 --max-tasks-per-child=1"
CELERYD_LOG_FILE="/var/ippidb-{{ http_port }}-celery/celery%n%I.log"
CELERYD_PID_FILE="/var/ippidb-{{ http_port }}-celery/celery%n.pid"
CELERYD_LOG_LEVEL="DEBUG"
CELERYD_LOG_LEVEL="INFO"
CELERYD_USER="celery-{{ http_port }}"
CELERYD_GROUP="ippidb"
CELERYD_QUEUE="celery-{{ http_port }}"
CELERY_CREATE_DIRS=1
SYSTEMD_LOG_LEVEL=debug
DJANGO_SETTINGS_MODULE=ippisite.{{ ansible_hostname }}_settings
BABEL_LIBDIR=/usr/lib64/openbabel/
\ No newline at end of file
......@@ -12,7 +12,11 @@
- name: Create celery user
user: name=celery-{{ http_port }} groups={{ deploy_user_name }} append=yes state=present createhome=yes
become: true
register: newuser
register: newuser
- name: Set the path to {{ deploy_user_name }} home to executable by group so that celery user can cd into it
file:
path: /home/{{ deploy_user_name }}
mode: g+x
# Install basic non-virtualenv requirements
#
- name: install git
......
[flake8]
max-line-length = 120
ignore = W503
exclude = */migrations/*.py, manage.py, docs/source/conf.py
exclude = */migrations/*.py, manage.py, docs/source/conf.py, get-pip.py
......@@ -14,6 +14,7 @@ ippisite/db.sqlite3
django.mo
ippisite/.idea/
db.sqlite3
tests_contribute_cache.sqlite
#bryan custom
*IPPIDB_PPI.xlsx*
......
......@@ -3,6 +3,8 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXAPI = sphinx-apidoc
SPHINXAPISRC = ..
SPHINXBUILD = sphinx-build
SOURCEDIR = source
BUILDDIR = build
......@@ -16,4 +18,6 @@ help:
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
\ No newline at end of file
@$(SPHINXAPI) -o $(SOURCEDIR) $(SPHINXAPISRC)
$(PYTHON) ../manage.py graph_models ippidb --dot > source/db.dot
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
......@@ -19,24 +19,26 @@ import os
import sys
import matplotlib
# avoid using tkinter with matplotlib
matplotlib.use('agg')
matplotlib.use("agg")
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath("../.."))
import django
os.environ['DJANGO_SETTINGS_MODULE'] = 'ippisite.settings'
os.environ["DJANGO_SETTINGS_MODULE"] = "ippisite.settings"
django.setup()
# -- Project information -----------------------------------------------------
project = 'iPPI-DB'
copyright = '2018, Rachel Torchet, Alexandra Moine-Franel, Hélène Borges, Bryan Brancotte, Olivia Doppelt-Azeroual, Fabien Mareuil, Hervé Ménager, Olivier Sperandio'
author = 'Rachel Torchet, Alexandra Moine-Franel, Hélène Borges, Bryan Brancotte, Olivia Doppelt-Azeroual, Fabien Mareuil, Hervé Ménager, Olivier Sperandio'
project = "iPPI-DB"
copyright = "2018, Rachel Torchet, Alexandra Moine-Franel, Hélène Borges, Bryan Brancotte, Olivia Doppelt-Azeroual, Fabien Mareuil, Hervé Ménager, Olivier Sperandio"
author = "Rachel Torchet, Alexandra Moine-Franel, Hélène Borges, Bryan Brancotte, Olivia Doppelt-Azeroual, Fabien Mareuil, Hervé Ménager, Olivier Sperandio"
# The short X.Y version
version = ''
version = ""
# The full version, including alpha/beta/rc tags
release = ''
release = ""
# -- General configuration ---------------------------------------------------
......@@ -49,25 +51,26 @@ release = ''
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autosummary',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
'sphinx.ext.graphviz'
"sphinx.ext.autosummary",
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.coverage",
"sphinx.ext.viewcode",
"sphinx.ext.graphviz",
"sphinxcontrib.bibtex",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......@@ -90,7 +93,7 @@ pygments_style = None
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
......@@ -102,7 +105,7 @@ html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
......@@ -118,7 +121,7 @@ html_static_path = ['_static']
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'iPPI-DBdoc'
htmlhelp_basename = "iPPI-DBdoc"
# -- Options for LaTeX output ------------------------------------------------
......@@ -127,15 +130,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
......@@ -145,8 +145,13 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'iPPI-DB.tex', 'iPPI-DB Documentation',
'Rachel Torchet, Alexandra Moine-Franel, Hélène Borges, Bryan Brancotte, Olivia Doppelt-Azeroual, Fabien Mareuil, Hervé Ménager, Olivier Sperandio', 'manual'),
(
master_doc,
"iPPI-DB.tex",
"iPPI-DB Documentation",
"Rachel Torchet, Alexandra Moine-Franel, Hélène Borges, Bryan Brancotte, Olivia Doppelt-Azeroual, Fabien Mareuil, Hervé Ménager, Olivier Sperandio",
"manual",
),
]
......@@ -154,10 +159,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'ippi-db', 'iPPI-DB Documentation',
[author], 1)
]
man_pages = [(master_doc, "ippi-db", "iPPI-DB Documentation", [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
......@@ -166,9 +168,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'iPPI-DB', 'iPPI-DB Documentation',
author, 'iPPI-DB', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"iPPI-DB",
"iPPI-DB Documentation",
author,
"iPPI-DB",
"One line description of project.",
"Miscellaneous",
),
]
......@@ -187,7 +195,7 @@ epub_title = project
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
epub_exclude_files = ["search.html"]
# -- Extension configuration -------------------------------------------------
......@@ -195,16 +203,16 @@ epub_exclude_files = ['search.html']
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None}
intersphinx_mapping = {"https://docs.python.org/": None}
# -- Extension configuration -------------------------------------------------i
autoclass_content = "both" # include both class docstring and __init__
autodoc_default_flags = [
# Make sure that any autodoc declarations show the right members
"members",
"private-members",
"show-inheritance",
# Make sure that any autodoc declarations show the right members
"members",
"private-members",
"show-inheritance",
]
autosummary_generate = True # Make _autosummary files and include them
napoleon_numpy_docstring = False # Force consistency, leave only Google
......@@ -212,7 +220,11 @@ napoleon_use_rtype = False # More legible
# The suffix of source filenames.
autosummary_generate = True
exclude_patterns = ['_build']
exclude_patterns = ["_build"]
#do not try to import tkinter for sphinx
autodoc_mock_imports = ['_tkinter']
\ No newline at end of file
# do not try to import tkinter for sphinx
autodoc_mock_imports = ["_tkinter"]
bibtex_bibfiles = [
"refs.bib",
]
......@@ -51,20 +51,21 @@ You can then navigate to the django admin interface of iPPI-DB, and create an en
.. image:: img/ORCID_conf_7.png
:width: 100%
GitHub authentication configuration
.. GitHub authentication is commented because it does not currently work
.. GitHub authentication configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The configuration for GitHub authentication follows the same principle: configure the app on the provider website, then enter the provided `Client ID` and `Client secret`
on the django admin interface website.
.. image:: img/Github_conf_1.png
:width: 100%
.. image:: img/Github_conf_2.png
:width: 100%
.. image:: img/Github_conf_3.png
:width: 100%
.. The configuration for GitHub authentication follows the same principle: configure the app on the provider website, then enter the provided `Client ID` and `Client secret`
on the django admin interface website.
..
.. image:: img/Github_conf_1.png
:width: 100%
..
.. image:: img/Github_conf_2.png
:width: 100%
..
.. image:: img/Github_conf_3.png
:width: 100%
......
This diff is collapsed.
......@@ -18,6 +18,7 @@ These pages contain the documentation for technical maintenance and development
install
configuration
database
webservices
modules
......
This diff is collapsed.
This diff is collapsed.
......@@ -9,6 +9,7 @@ This is the main ippidb module
forms
gx
models
tasks
tests
urls
utils
......
......@@ -172,20 +172,6 @@ class IdForm(forms.Form):
.first()
)
# def get_or_create(self):
# b = models.Bibliography.objects \
# .filter(id_source=self.cleaned_data["id_source"]).filter(source=self.cleaned_data["source"]) \
# .annotate(used=Count("refcompoundbiblio")) \
# .filter(used=0) \
# .first()
# if b is not None:
# return b, False
# else:
# return models.Bibliography.objects.create(
# source=self.cleaned_data["source"],
# id_source=self.cleaned_data["id_source"],
# ), True
""" Step 2 : BibliographyForm """
......@@ -424,10 +410,6 @@ class ComplexCompositionBaseFormSet(forms.BaseFormSet):
if form.cleaned_data.get("DELETE", False):
continue
complex_type_dict.add(form.cleaned_data.get("complex_type"))
if self.has_bound and self.has_partner and len(complex_type_dict) < 2:
self._non_form_errors.append(
_("You need at least one bound and one partner")
)
def __init__(
self,
......@@ -482,6 +464,7 @@ class PpiModelForm(ModelForm):
"data-olsontology": "mondo",
"data-selectpath": "https://www.ebi.ac.uk/ols/",
"olstype": "",
"class": "",
}
),
)
......@@ -491,12 +474,6 @@ class PpiModelForm(ModelForm):
required=False,
)
# other_diseases = forms.CharField(
# label=_("other_diseases_label"),
# help_text=_("other_diseases_help_text"),
# required=False,
# )
class Meta:
model = models.Ppi
fields = (
......@@ -506,9 +483,8 @@ class PpiModelForm(ModelForm):
"family_name",
"symmetry",
"pockets_nb", # pockets_nb is Ppi.pockets_nb in the xlsx file of #33
"selected_diseases",
"ols_diseases",
# 'other_diseases',
"selected_diseases",
)
widgets = {
"id": forms.HiddenInput(),
......@@ -535,17 +511,6 @@ class PpiModelForm(ModelForm):
self.fields["symmetry"].initial = symmetry.first()
self.fields["symmetry"].widget = forms.HiddenInput()
pdb_id = initial.get("pdb_id", None)
if pdb_id is not None:
# FIXME move PFAM choice to relevant form ;)
pfams = ws.get_pdb_pfam_mapping(pdb_id) # noqa: F841
# choices = self.fields["family_name"].choices
# for key, values in pfams.items():
# text = "{} ({})".format(values["name"], key)
# choices.append((text, text))
# self.fields["family_name"].choices = choices
# self.fields["family_name"].initial = choices[-1][0]
def full_clean(self):
super().full_clean()
if hasattr(self, "cleaned_data") and "family_name" in self.cleaned_data:
......@@ -573,13 +538,6 @@ class PpiModelForm(ModelForm):
name=name, identifier=identifier
)
self.instance.diseases.add(disease)
# for new_disease in self.cleaned_data['other_diseases'].split(','):
# new_disease = new_disease.strip()
# if len(new_disease) == 0:
# continue
# print(new_disease)
# disease, created = Disease.objects.get_or_create(name=new_disease)
# self.instance.diseases.add(disease)
self.instance.family = models.PpiFamily.objects.get(
id=self.cleaned_data["family"]
)
......@@ -593,7 +551,9 @@ TYPE_MOLECULE = (("smiles", "smiles"), ("iupac", "iupac"), ("sketch", "sketch"))
class CompoundForm(forms.Form):
compound_name = forms.CharField(
label=_("compound_name_label"), required=True, help_text=_(""),
label=_("compound_name_label"),
required=True,
help_text=_(""),
)
ligand_id = forms.CharField(
label=_("PDB Ligand ID"),
......@@ -604,7 +564,13 @@ class CompoundForm(forms.Form):
label=_("molecule_smiles_label"),
help_text=_(""),
required=False,
widget=forms.Textarea(attrs={"class": "molecule-composition", "rows": "9"}),
widget=forms.Textarea(
attrs={
"class": "molecule-composition",
"rows": "9",
"oninput": "showCanvas(this)",
}
),
)
molecule_iupac = forms.CharField(
label=_("molecule_iupac_label"),
......@@ -620,7 +586,9 @@ class CompoundForm(forms.Form):
def full_clean(self):
super().full_clean()
if not self.is_bound: # Stop further processing.
if (
not self.is_bound or self.cleaned_data.get("DELETE") is True
): # Stop further processing.
return
smiles = None
if (
......@@ -839,7 +807,11 @@ class BaseInlineNestedFormSet(forms.BaseInlineFormSet):
class CompoundActivityResultForm(ModelForm):
compound_name = forms.ChoiceField(choices=(), required=True)
activity_mol = forms.DecimalField(
label="Activity", required=True, max_digits=15, decimal_places=10, min_value=0,
label="Activity",
required=True,
max_digits=15,
decimal_places=10,
min_value=0,
)
activity_unit = forms.CharField(
label="Activity unit",
......@@ -872,6 +844,11 @@ class CompoundActivityResultForm(ModelForm):
"activity": widgets.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for f in self.fields.values():
f.widget.attrs.update({"class": "col-3"})
def has_changed(self):
"""
Test if the form has changed, we consider that it has not changed if it is not linked to an actual instance and
......@@ -1043,7 +1020,8 @@ CompoundActivityResultInlineFormset = inlineformset_factory(
class TestActivityDescriptionForm(forms.ModelForm):
test_name = CharFieldDataList(
data_class=models.TestActivityDescription, data_attr="test_name"
data_class=models.TestActivityDescription,
data_attr="test_name",
)
cell_line_name = CharFieldDataList(
......@@ -1068,6 +1046,11 @@ class TestActivityDescriptionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["test_type"].widget.attrs["onchange"] = "test_type_changed(this);"
self.fields["test_type"].widget.attrs.update({"class": "col-2"})
self.fields["test_name"].widget.attrs.update({"class": "col-10"})
self.fields["test_modulation_type"].widget.attrs.update({"class": "col-2"})
self.fields["nb_active_compounds"].widget.attrs.update({"class": "col-3"})
self.fields["cell_line_name"].widget.attrs.update({"class": "col-7"})
def has_changed(self):
"""
......@@ -1195,6 +1178,11 @@ class CompoundCytotoxicityResultForm(ModelForm):
fields = ("compound_name", "toxicity")
widgets = {"toxicity": forms.Select(choices=((True, "True"), (False, "False")))}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for f in self.fields.values():
f.widget.attrs.update({"class": "col-3"})
def has_changed(self):
"""
Test if the form has changed, we consider that it has not changed if it is not linked to an actual instance and
......@@ -1309,6 +1297,9 @@ class TestCytotoxDescriptionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["compound_concentration"].required = True
self.fields["cell_line_name"].widget.attrs.update({"class": "col"})
self.fields["compound_concentration"].widget.attrs.update({"class": "col"})
self.fields["test_name"].widget.attrs.update({"class": "col"})
def has_changed(self):
"""
......@@ -1403,10 +1394,19 @@ class CompoundPKResultForm(ModelForm):
exclude = ("compound", "test_pk_description")
widgets = {
"tolerated": forms.Select(
choices=((True, "True"), (False, "False"), (None, "Null"))
choices=((True, "True"), (False, "False"), (None, "Unknown"))
)
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for f in self.fields.values():
f.widget.attrs.update({"class": "col-3"})
if isinstance(f, forms.BooleanField) and not isinstance(
f.widget, forms.Select
):
f.widget.attrs.update({"class": "col-3 mb-4"})
def has_changed(self):
"""
Test if the form has changed, we consider that it has not changed if it is not linked to an actual instance and
......@@ -1509,10 +1509,6 @@ class TestPKDescriptionForm(forms.ModelForm):
data_class=models.TestPKDescription, data_attr="test_name"
)
cell_line_name = CharFieldDataList(
data_class=models.CellLine, data_attr="name", label=_("Cell line")
)
class Meta:
model = models.TestPKDescription
fields = "__all__"
......@@ -1520,8 +1516,10 @@ class TestPKDescriptionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for f in ["administration_mode", "concentration", "dose", "dose_interval"]:
for f in ["administration_mode", "dose"]:
self.fields[f].required = True
for f in self.fields.values():
f.widget.attrs.update({"class": "col-3"})
def has_changed(self):
"""
......@@ -1538,23 +1536,6 @@ class TestPKDescriptionForm(forms.ModelForm):
return False
return super().has_changed()
def save(self, commit=True):
"""
Before an actual save, we set the foreign key that have been created in the meantime from unique identifier
(cell_line_name, protein_complex) we where provided at the initialization of the form, and/or the input of the
user.
:param commit:
:return:
"""
# right
if hasattr(self, "cleaned_data"):
if "cell_line_name" in self.cleaned_data:
cell_line, created = models.CellLine.objects.get_or_create(
name=self.cleaned_data["cell_line_name"]
)
self.instance.cell_line = cell_line
return super().save(commit=commit)
class TestPKDescriptionBaseModelFormSet(BaseInlineNestedFormSet):
__compound_names = None
......@@ -1737,15 +1718,19 @@ class TestsForm(forms.Form):
pkRes_tolerated = forms.ChoiceField(
label="Tolerated", widget=forms.TextInput(), required=False
)
pkRes_auc = forms.IntegerField(label="AUC", initial=1, required=False)
pkRes_clearance = forms.DecimalField(label="Clearance", required=False)
pkRes_cmax = forms.DecimalField(label="C max", required=False)
pkRes_auc_av = forms.BooleanField(label="AUC available", initial=1, required=False)
pkRes_clearance_av = forms.BooleanField(label="Clearance available", required=False)
pkRes_cmax_av = forms.BooleanField(
label="Maximal concentration available", required=False
)
pkRes_oral_bioavailability = forms.IntegerField(
label="Oral bio-availability", initial=1, required=False
)
pkRes_t_demi = forms.IntegerField(label="T 1/2", initial=1, required=False)
pkRes_t_max = forms.IntegerField(label="T max", initial=1, required=False)
pkRes_voldistribution = forms.DecimalField(label="Voldistribution", required=False)
pkRes_voldistribution_av = forms.BooleanField(
label="Volume distribution (Vd) available", required=False
)