Skip to content

Commit 2c0914c

Browse files
authored
Merge pull request #78 from aiidalab/release_1.0.0b5
Release 1.0.0b5
2 parents c4b78e3 + c0bf29a commit 2c0914c

File tree

7 files changed

+428
-70
lines changed

7 files changed

+428
-70
lines changed

aiidalab_widgets_base/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from .process import ProcessFollowerWidget, ProgressBarWidget, RunningCalcJobOutputWidget, SubmitButtonWidget # noqa
1414
from .structures import StructureManagerWidget # noqa
1515
from .structures import StructureBrowserWidget, StructureExamplesWidget, StructureUploadWidget, SmilesWidget # noqa
16+
from .structures import BasicStructureEditor # noqa
1617
from .structures_multi import MultiStructureUploadWidget # noqa
1718
from .viewers import viewer # noqa
1819

19-
__version__ = "1.0.0b4"
20+
__version__ = "1.0.0b5"

aiidalab_widgets_base/codes.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import ipywidgets as ipw
66
from IPython.display import clear_output
7-
from traitlets import Dict, Instance, Unicode, Union, link, validate
7+
from traitlets import Bool, Dict, Instance, Unicode, Union, link, validate
88

99
from aiida.orm import Code, QueryBuilder, User
1010

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

37-
def __init__(self, input_plugin, text='Select code:', path_to_root='../', **kwargs):
44+
def __init__(self, input_plugin, description='Select code:', path_to_root='../', **kwargs):
3845
"""Dropdown for Codes for one input plugin.
3946
40-
:param input_plugin: Input plugin of codes to show
41-
:type input_plugin: str
42-
:param text: Text to display before dropdown
43-
:type text: str
47+
input_plugin (str): Input plugin of codes to show.
48+
49+
description (str): Description to display before the dropdown.
4450
"""
51+
self.output = ipw.Output()
4552

4653
self.input_plugin = input_plugin
47-
self.output = ipw.Output()
4854

49-
self.dropdown = ipw.Dropdown(optionsdescription=text, disabled=True, value=None)
55+
self.dropdown = ipw.Dropdown(description=description, disabled=True, value=None)
5056
link((self, 'codes'), (self.dropdown, 'options'))
5157
link((self.dropdown, 'value'), (self, 'selected_code'))
5258

53-
self._btn_refresh = ipw.Button(description="Refresh", layout=ipw.Layout(width="70px"))
54-
self._btn_refresh.on_click(self.refresh)
59+
btn_refresh = ipw.Button(description="Refresh", layout=ipw.Layout(width="70px"))
60+
btn_refresh.on_click(self.refresh)
61+
62+
self.observe(self.refresh, names=['allow_disabled_computers', 'allow_hidden_codes'])
5563

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

61-
children = [ipw.HBox([self.dropdown, self._btn_refresh, self._setup_another]), self.output]
69+
children = [ipw.HBox([self.dropdown, btn_refresh, self._setup_another]), self.output]
6270

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

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

70-
querybuild = QueryBuilder()
71-
querybuild.append(Code,
72-
filters={
73-
'attributes.input_plugin': {
74-
'==': self.input_plugin
75-
},
76-
'extras.hidden': {
77-
"~==": True
78-
}
79-
},
80-
project=['*'])
81-
82-
# Only codes on computers configured for the current user.
78+
user = User.objects.get_default()
79+
8380
return {
8481
self._full_code_label(c[0]): c[0]
85-
for c in querybuild.all()
86-
if c[0].computer.is_user_configured(User.objects.get_default())
82+
for c in QueryBuilder().append(Code, filters={
83+
'attributes.input_plugin': self.input_plugin
84+
}).all()
85+
if c[0].computer.is_user_configured(user) and (self.allow_hidden_codes or not c[0].hidden) and
86+
(self.allow_disabled_computers or c[0].computer.is_user_enabled(user))
8787
}
8888

8989
@staticmethod

aiidalab_widgets_base/computers.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import pexpect
88
import ipywidgets as ipw
99
from IPython.display import clear_output
10-
from traitlets import Bool, Dict, Instance, Int, Unicode, Union, link, observe, validate
10+
from traitlets import Bool, Dict, Instance, Int, Unicode, Union, link, validate
1111

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

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

672-
def __init__(self, text='Select computer:', path_to_root='../', **kwargs):
674+
def __init__(self, description='Select computer:', path_to_root='../', **kwargs):
673675
"""Dropdown for configured AiiDA Computers.
674676
675-
text (str): Text to display before dropdown.
677+
description (str): Text to display before dropdown.
676678
677679
path_to_root (str): Path to the app's root folder.
678680
"""
679681

680682
self.output = ipw.Output()
681683

682-
if 'allow_select_disabled' in kwargs:
683-
self.allow_select_disabled = kwargs['allow_select_disabled']
684-
685684
self._dropdown = ipw.Dropdown(options={},
686685
value=None,
687-
description=text,
686+
description=description,
688687
style={'description_width': 'initial'},
689688
disabled=True)
690689
link((self, 'computers'), (self._dropdown, 'options'))
@@ -693,6 +692,8 @@ def __init__(self, text='Select computer:', path_to_root='../', **kwargs):
693692
btn_refresh = ipw.Button(description="Refresh", layout=ipw.Layout(width="70px"))
694693
btn_refresh.on_click(self.refresh)
695694

695+
self.observe(self.refresh, names='allow_select_disabled')
696+
696697
self._setup_another = ipw.HTML(
697698
value="""<a href={path_to_root}aiidalab-widgets-base/setup_computer.ipynb target="_blank">
698699
Setup new computer</a>""".format(path_to_root=path_to_root))
@@ -713,7 +714,6 @@ def _get_computers(self):
713714
if c[0].is_user_configured(user) and (self.allow_select_disabled or c[0].is_user_enabled(user))
714715
}
715716

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Useful functions that provide access to some data. """
2+
from ase import Atom, Atoms
3+
import numpy as np
4+
import ipywidgets as ipw
5+
6+
# The first atom is anchoring, so the new bond will be connecting it
7+
# The direction of the new bond is (-1, -1, -1).
8+
LIGANDS = {
9+
'Select ligand':
10+
0,
11+
'Methyl -CH3': [('C', 0, 0, 0), ('H', 0.23962342, -0.47699124, 0.78585262),
12+
('H', 0.78584986, 0.23962732, -0.47698795), ('H', -0.47699412, 0.78585121, 0.23962671)],
13+
'Methylene =CH2': [('C', 0, 0, 0), ('H', -0.39755349, 0.59174911, 0.62728004),
14+
('H', 0.94520686, -0.04409933, -0.07963039)],
15+
'Hydroxy -OH': [('O', 0, 0, 0), ('H', 0.87535922, -0.3881659, 0.06790889)],
16+
'Amine -NH2': [('N', 0, 0, 0), ('H', 0.7250916, -0.56270993, 0.42151063),
17+
('H', -0.56261958, 0.4215284, 0.72515241)],
18+
}
19+
20+
21+
class LigandSelectorWidget(ipw.Dropdown):
22+
"""Class to select ligands that are returned as `Atoms` object"""
23+
24+
def __init__(self, value=0, description="Select ligand", **kwargs):
25+
self.style = {'description_width': 'initial'}
26+
self.layout = {'width': 'initial'}
27+
super().__init__(value=value, description=description, options=LIGANDS, **kwargs)
28+
29+
def rotate(self, align_to=(0, 0, 1), remove_anchor=False):
30+
"""Rotate group in such a way that vector which was (-1,-1,-1)
31+
is alligned with align_to."""
32+
33+
vect = np.array(align_to)
34+
norm = np.linalg.norm(vect)
35+
36+
if self.value == 0:
37+
return None
38+
39+
mol = Atoms()
40+
for atm in self.value:
41+
mol.append(Atom(atm[0], atm[1:]))
42+
43+
# Bad cases.
44+
if norm == 0.0:
45+
vect = np.array((1, 1, 1)) / np.sqrt(3)
46+
else:
47+
vect = vect / norm
48+
49+
mol.rotate((1, 1, 1), vect)
50+
51+
if remove_anchor:
52+
del mol[0]
53+
54+
return mol
55+
56+
@property
57+
def anchoring_atom(self):
58+
"""Return anchoring atom chemical symbol."""
59+
if self.value == 0:
60+
return None
61+
return self.value[0][0]

0 commit comments

Comments
 (0)