Skip to content

Commit e9b11c5

Browse files
authored
Merge pull request #64 from aiidalab/release_1.0.0b3
2 parents 36f9eaf + 6e15475 commit e9b11c5

File tree

8 files changed

+362
-302
lines changed

8 files changed

+362
-302
lines changed

aiidalab_widgets_base/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
from .structures_multi import MultiStructureUploadWidget # noqa
1717
from .viewers import viewer # noqa
1818

19-
__version__ = "1.0.0b2"
19+
__version__ = "1.0.0b3"

aiidalab_widgets_base/databases.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
"""Widgets that allow to query online databases."""
22
import ipywidgets as ipw
3+
from traitlets import Instance, default
4+
from ase import Atoms
35

46
from aiida.tools.dbimporters.plugins.cod import CodDbImporter
57

68

79
class CodQueryWidget(ipw.VBox):
810
'''Query structures in Crystallography Open Database (COD)
911
Useful class members:
10-
:ivar has_structure: link to a method to be overloaded. It is called evey time when `self.drop_structure`
11-
widget has changed its name
12-
:vartype has_structure: function
13-
'''
12+
:ivar structure(Atoms): trait that contains the selected structure, None if structure is not selected.'''
13+
14+
structure = Instance(Atoms, allow_none=True)
1415

1516
def __init__(self, **kwargs):
1617
description = ipw.HTML("""<h3>Get crystal structures from
@@ -47,8 +48,6 @@ def __init__(self, **kwargs):
4748
style=style,
4849
layout=layout)
4950
self.link = ipw.HTML("Link to the web-page will appear here")
50-
self.structure_ase = None
51-
5251
self.btn_query.on_click(self._on_click_query)
5352
self.drop_structure.observe(self._on_select_structure, names=['value'])
5453

@@ -101,14 +100,12 @@ def _on_select_structure(self, change):
101100
"""When a structure was selected."""
102101
selected = change['new']
103102
if selected['status'] is False:
104-
self.structure_ase = None
103+
self.structure = None
105104
return
106-
self.structure_ase = selected['cif'].get_ase()
107-
formula = self.structure_ase.get_chemical_formula()
105+
self.structure = selected['cif'].get_ase()
108106
struct_url = selected['url'].split('.cif')[0] + '.html'
109107
self.link.value = '<a href="{}" target="_blank">COD entry {}</a>'.format(struct_url, selected['id'])
110-
if self.on_structure_selection is not None:
111-
self.on_structure_selection(structure_ase=self.structure_ase, name=formula)
112108

113-
def on_structure_selection(self, structure_ase, name):
114-
pass
109+
@default('structure')
110+
def _default_structure(self): # pylint: disable=no-self-use
111+
return None

aiidalab_widgets_base/process.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
"""Widgets to work with processes."""
22

33
import os
4-
from ipywidgets import Textarea, VBox
4+
from ipywidgets import Button, HTML, IntProgress, Layout, Textarea, VBox
5+
6+
# AiiDA imports
7+
from aiida.engine import submit
8+
from aiida.orm import CalcJobNode, ProcessNode, WorkChainNode
59

610

711
def get_running_calcs(process):
812
"""Takes a process and returns a list of running calculations. The running calculations
913
can be either the process itself or its running children."""
1014

11-
from aiida.orm import CalcJobNode, ProcessNode, WorkChainNode
12-
1315
# If a process is a running calculation - returning it
1416
if issubclass(type(process), CalcJobNode) and not process.is_sealed:
1517
return [process]
@@ -28,19 +30,20 @@ def get_running_calcs(process):
2830
class SubmitButtonWidget(VBox):
2931
"""Submit button class that creates submit button jupyter widget."""
3032

31-
def __init__(self, process, widgets_values):
33+
def __init__(self, process, input_dictionary_function, description="Submit"):
3234
"""Submit Button
3335
:process: work chain to run
3436
:param_funtion: the function that generates input parameters dictionary
3537
"""
36-
from ipywidgets import Button, Output
3738

3839
self.process = None
3940
self._process_class = process
40-
self.widgets_values = widgets_values
41-
self.btn_submit = Button(description="Submit", disabled=False)
41+
self._run_after_submitted = []
42+
43+
self.input_dictionary_function = input_dictionary_function
44+
self.btn_submit = Button(description=description, disabled=False)
4245
self.btn_submit.on_click(self.on_btn_submit_press)
43-
self.submit_out = Output()
46+
self.submit_out = HTML('')
4447
children = [
4548
self.btn_submit,
4649
self.submit_out,
@@ -50,30 +53,33 @@ def __init__(self, process, widgets_values):
5053
def on_click(self, function):
5154
self.btn_submit.on_click(function)
5255

53-
def on_btn_submit_press(self, _):
56+
def on_btn_submit_press(self, _=None):
5457
"""When submit button is pressed."""
55-
from IPython.display import clear_output
56-
from aiida.engine import submit
57-
58-
with self.submit_out:
59-
clear_output()
58+
self.submit_out.value = ''
59+
input_dict = self.input_dictionary_function()
60+
if input_dict is None:
61+
self.submit_out.value = "SubmitButtonWidget: did not recieve input dictionary."
62+
else:
6063
self.btn_submit.disabled = True
61-
input_dict = self.widgets_values()
6264
self.process = submit(self._process_class, **input_dict)
63-
print("Submitted process {}".format(self.process))
64-
return
65+
self.submit_out.value = "Submitted process {}".format(self.process)
66+
for func in self._run_after_submitted:
67+
func(self.process)
68+
69+
def on_submitted(self, function):
70+
"""Run functions after a process has been submitted sucesfully."""
71+
self._run_after_submitted.append(function)
6572

6673

6774
class ProcessFollowerWidget(VBox):
6875
"""A Widget that follows a process until finished."""
6976

7077
def __init__(self, process, followers=None, update_interval=0.1, **kwargs):
7178
"""Initiate all the followers."""
72-
from aiida.orm import ProcessNode
73-
7479
if not isinstance(process, ProcessNode):
7580
raise TypeError("Expecting an object of type {}, got {}".format(ProcessNode, type(process)))
7681
self.process = process
82+
self._run_after_completed = []
7783
self.update_interval = update_interval
7884
self.followers = []
7985
if followers is not None:
@@ -102,13 +108,18 @@ def follow(self, detach=False):
102108
update_state.start()
103109
else:
104110
self._follow()
111+
for func in self._run_after_completed:
112+
func(self.process)
113+
114+
def on_completed(self, function):
115+
"""Run functions after a process has been completed."""
116+
self._run_after_completed.append(function)
105117

106118

107119
class ProgressBarWidget(VBox):
108120
"""A bar showing the proggress of a process."""
109121

110122
def __init__(self, process, **kwargs):
111-
from ipywidgets import HTML, IntProgress, Layout
112123

113124
self.process = process
114125
self.correspondance = {

0 commit comments

Comments
 (0)