Skip to content

Commit

Permalink
Merge pull request #78 from aiidalab/release_1.0.0b5
Browse files Browse the repository at this point in the history
Release 1.0.0b5
  • Loading branch information
yakutovicha authored May 6, 2020
2 parents c4b78e3 + c0bf29a commit 2c0914c
Show file tree
Hide file tree
Showing 7 changed files with 428 additions and 70 deletions.
3 changes: 2 additions & 1 deletion aiidalab_widgets_base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
from .process import ProcessFollowerWidget, ProgressBarWidget, RunningCalcJobOutputWidget, SubmitButtonWidget # noqa
from .structures import StructureManagerWidget # noqa
from .structures import StructureBrowserWidget, StructureExamplesWidget, StructureUploadWidget, SmilesWidget # noqa
from .structures import BasicStructureEditor # noqa
from .structures_multi import MultiStructureUploadWidget # noqa
from .viewers import viewer # noqa

__version__ = "1.0.0b4"
__version__ = "1.0.0b5"
52 changes: 26 additions & 26 deletions aiidalab_widgets_base/codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import ipywidgets as ipw
from IPython.display import clear_output
from traitlets import Dict, Instance, Unicode, Union, link, validate
from traitlets import Bool, Dict, Instance, Unicode, Union, link, validate

from aiida.orm import Code, QueryBuilder, User

Expand All @@ -30,35 +30,43 @@ class CodeDropdown(ipw.VBox):
codes(Dict): Trait that contains a dictionary (label => Code instance) for all
codes found in the AiiDA database for the selected plugin. It is linked
to the 'options' trait of the `self.dropdown` widget.
allow_hidden_codes(Bool): Trait that defines whether to show hidden codes or not.
allow_disabled_computers(Bool): Trait that defines whether to show codes on disabled
computers.
"""
selected_code = Union([Unicode(), Instance(Code)], allow_none=True)
codes = Dict(allow_none=True)
allow_hidden_codes = Bool(False)
allow_disabled_computers = Bool(False)

def __init__(self, input_plugin, text='Select code:', path_to_root='../', **kwargs):
def __init__(self, input_plugin, description='Select code:', path_to_root='../', **kwargs):
"""Dropdown for Codes for one input plugin.
:param input_plugin: Input plugin of codes to show
:type input_plugin: str
:param text: Text to display before dropdown
:type text: str
input_plugin (str): Input plugin of codes to show.
description (str): Description to display before the dropdown.
"""
self.output = ipw.Output()

self.input_plugin = input_plugin
self.output = ipw.Output()

self.dropdown = ipw.Dropdown(optionsdescription=text, disabled=True, value=None)
self.dropdown = ipw.Dropdown(description=description, disabled=True, value=None)
link((self, 'codes'), (self.dropdown, 'options'))
link((self.dropdown, 'value'), (self, 'selected_code'))

self._btn_refresh = ipw.Button(description="Refresh", layout=ipw.Layout(width="70px"))
self._btn_refresh.on_click(self.refresh)
btn_refresh = ipw.Button(description="Refresh", layout=ipw.Layout(width="70px"))
btn_refresh.on_click(self.refresh)

self.observe(self.refresh, names=['allow_disabled_computers', 'allow_hidden_codes'])

# FOR LATER: use base_url here, when it will be implemented in the appmode.
self._setup_another = ipw.HTML(value="""<a href={path_to_root}aiidalab-widgets-base/setup_code.ipynb?
label={label}&plugin={plugin} target="_blank">Setup new code</a>""".format(
path_to_root=path_to_root, label=input_plugin, plugin=input_plugin))

children = [ipw.HBox([self.dropdown, self._btn_refresh, self._setup_another]), self.output]
children = [ipw.HBox([self.dropdown, btn_refresh, self._setup_another]), self.output]

super().__init__(children=children, **kwargs)

Expand All @@ -67,23 +75,15 @@ def __init__(self, input_plugin, text='Select code:', path_to_root='../', **kwar
def _get_codes(self):
"""Query the list of available codes."""

querybuild = QueryBuilder()
querybuild.append(Code,
filters={
'attributes.input_plugin': {
'==': self.input_plugin
},
'extras.hidden': {
"~==": True
}
},
project=['*'])

# Only codes on computers configured for the current user.
user = User.objects.get_default()

return {
self._full_code_label(c[0]): c[0]
for c in querybuild.all()
if c[0].computer.is_user_configured(User.objects.get_default())
for c in QueryBuilder().append(Code, filters={
'attributes.input_plugin': self.input_plugin
}).all()
if c[0].computer.is_user_configured(user) and (self.allow_hidden_codes or not c[0].hidden) and
(self.allow_disabled_computers or c[0].computer.is_user_enabled(user))
}

@staticmethod
Expand Down
16 changes: 8 additions & 8 deletions aiidalab_widgets_base/computers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pexpect
import ipywidgets as ipw
from IPython.display import clear_output
from traitlets import Bool, Dict, Instance, Int, Unicode, Union, link, observe, validate
from traitlets import Bool, Dict, Instance, Int, Unicode, Union, link, validate

from aiida.common import NotExistent
from aiida.orm import Computer, QueryBuilder, User
Expand Down Expand Up @@ -663,28 +663,27 @@ class ComputerDropdown(ipw.VBox):
computers(Dict): Trait that contains a dictionary (label => Computer instance) for all
computers found in the AiiDA database. It is linked to the 'options' trait of
`self._dropdown` widget.
allow_select_disabled(Bool): Trait that defines whether to show disabled computers.
"""

selected_computer = Union([Unicode(), Instance(Computer)], allow_none=True)
computers = Dict(allow_none=True)
allow_select_disabled = Bool(False)

def __init__(self, text='Select computer:', path_to_root='../', **kwargs):
def __init__(self, description='Select computer:', path_to_root='../', **kwargs):
"""Dropdown for configured AiiDA Computers.
text (str): Text to display before dropdown.
description (str): Text to display before dropdown.
path_to_root (str): Path to the app's root folder.
"""

self.output = ipw.Output()

if 'allow_select_disabled' in kwargs:
self.allow_select_disabled = kwargs['allow_select_disabled']

self._dropdown = ipw.Dropdown(options={},
value=None,
description=text,
description=description,
style={'description_width': 'initial'},
disabled=True)
link((self, 'computers'), (self._dropdown, 'options'))
Expand All @@ -693,6 +692,8 @@ def __init__(self, text='Select computer:', path_to_root='../', **kwargs):
btn_refresh = ipw.Button(description="Refresh", layout=ipw.Layout(width="70px"))
btn_refresh.on_click(self.refresh)

self.observe(self.refresh, names='allow_select_disabled')

self._setup_another = ipw.HTML(
value="""<a href={path_to_root}aiidalab-widgets-base/setup_computer.ipynb target="_blank">
Setup new computer</a>""".format(path_to_root=path_to_root))
Expand All @@ -713,7 +714,6 @@ def _get_computers(self):
if c[0].is_user_configured(user) and (self.allow_select_disabled or c[0].is_user_enabled(user))
}

@observe('allow_select_disabled')
def refresh(self, _=None):
"""Refresh the list of configured computers."""

Expand Down
61 changes: 61 additions & 0 deletions aiidalab_widgets_base/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Useful functions that provide access to some data. """
from ase import Atom, Atoms
import numpy as np
import ipywidgets as ipw

# The first atom is anchoring, so the new bond will be connecting it
# The direction of the new bond is (-1, -1, -1).
LIGANDS = {
'Select ligand':
0,
'Methyl -CH3': [('C', 0, 0, 0), ('H', 0.23962342, -0.47699124, 0.78585262),
('H', 0.78584986, 0.23962732, -0.47698795), ('H', -0.47699412, 0.78585121, 0.23962671)],
'Methylene =CH2': [('C', 0, 0, 0), ('H', -0.39755349, 0.59174911, 0.62728004),
('H', 0.94520686, -0.04409933, -0.07963039)],
'Hydroxy -OH': [('O', 0, 0, 0), ('H', 0.87535922, -0.3881659, 0.06790889)],
'Amine -NH2': [('N', 0, 0, 0), ('H', 0.7250916, -0.56270993, 0.42151063),
('H', -0.56261958, 0.4215284, 0.72515241)],
}


class LigandSelectorWidget(ipw.Dropdown):
"""Class to select ligands that are returned as `Atoms` object"""

def __init__(self, value=0, description="Select ligand", **kwargs):
self.style = {'description_width': 'initial'}
self.layout = {'width': 'initial'}
super().__init__(value=value, description=description, options=LIGANDS, **kwargs)

def rotate(self, align_to=(0, 0, 1), remove_anchor=False):
"""Rotate group in such a way that vector which was (-1,-1,-1)
is alligned with align_to."""

vect = np.array(align_to)
norm = np.linalg.norm(vect)

if self.value == 0:
return None

mol = Atoms()
for atm in self.value:
mol.append(Atom(atm[0], atm[1:]))

# Bad cases.
if norm == 0.0:
vect = np.array((1, 1, 1)) / np.sqrt(3)
else:
vect = vect / norm

mol.rotate((1, 1, 1), vect)

if remove_anchor:
del mol[0]

return mol

@property
def anchoring_atom(self):
"""Return anchoring atom chemical symbol."""
if self.value == 0:
return None
return self.value[0][0]
Loading

0 comments on commit 2c0914c

Please sign in to comment.