Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support AiiDA 2.0 and new AiiDAlab Docker image #80

Merged
merged 123 commits into from
Dec 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
3a0e814
Fix path to worklow package in new Docker image
danielhollas Oct 3, 2022
f46e96e
Temporarily switch aiida-orca to aiida2 branch
danielhollas Oct 17, 2022
9b38398
Exit code 0 in post_install
danielhollas Oct 17, 2022
1f6a2cd
importlib fix
danielhollas Oct 18, 2022
e4b8fb5
explicit rdkit dependency, without version constraint for now
danielhollas Oct 18, 2022
a292624
Temporarily add openbabel as dependency
danielhollas Oct 18, 2022
178b39c
Revert "Temporarily add openbabel as dependency"
danielhollas Oct 27, 2022
fe7f22f
Fix TrajectoryDataViewer registration
danielhollas Nov 1, 2022
3191081
WIP: Fix CalcJobViewer
danielhollas Nov 1, 2022
7b42c26
Merge branch 'main' into aiida2
danielhollas Nov 2, 2022
3d0dee2
WIP: process_uuid
danielhollas Nov 2, 2022
232c584
Remove unneeded import
danielhollas Nov 2, 2022
4cdb4f7
Fix code handling
danielhollas Nov 2, 2022
5f2a20a
Trying to fix CalcJobViewer
danielhollas Nov 2, 2022
3186e17
Bumb AWB requirements
danielhollas Nov 2, 2022
0047792
Merge branch 'main' into aiida2
danielhollas Nov 3, 2022
6f128d9
Fix?
danielhollas Nov 3, 2022
7bc6e03
Fix submission
danielhollas Nov 3, 2022
f684c03
Merge branch 'main' into aiida2
danielhollas Nov 4, 2022
c1d1575
Fix SpectrumWidget notebook
danielhollas Nov 4, 2022
55768cd
Temporarily disable test
danielhollas Nov 4, 2022
064586c
Switch to the aiida-orca@atmospec branch that will collect unmerged PRs
danielhollas Nov 9, 2022
62ad610
Merge branch 'main' into aiida2
danielhollas Nov 9, 2022
c5fc6d4
Merge branch 'main' into aiida2
danielhollas Nov 15, 2022
a46c7e5
Merge branch 'main' into aiida2
danielhollas Nov 15, 2022
c083e68
Bump version to indicate breaking changes
danielhollas Nov 15, 2022
16c1345
Add optimization label to workflow
danielhollas Nov 15, 2022
f232434
Relax AWB requirement
danielhollas Nov 15, 2022
0ae692d
Merge branch 'main' into aiida2
danielhollas Nov 15, 2022
7e60783
Run aiida-upgrade
danielhollas Nov 16, 2022
26157c1
AWB update + deprecation warnings cleanup
danielhollas Nov 17, 2022
633273b
Fix reordering of workchains
danielhollas Nov 17, 2022
d8ae23d
Paralelize EOM-CCSD calculations
danielhollas Nov 16, 2022
1b28a43
Fix exp. spectrum plotting
danielhollas Nov 17, 2022
87095de
[dev] Fix path to flake8 repo
danielhollas Nov 17, 2022
f660ed6
Trigger precommit
danielhollas Nov 17, 2022
13f7327
Trim example.ipynb
danielhollas Nov 17, 2022
923e985
Use verdi code create in post_install
danielhollas Nov 18, 2022
5f1389c
More deprecations
danielhollas Nov 20, 2022
d65a87d
core.code.installed
danielhollas Nov 21, 2022
7b3080f
fix post_install
danielhollas Nov 21, 2022
f1b9504
Fix categories in setup.cfg
danielhollas Nov 22, 2022
26fb41e
Bring back tests
danielhollas Dec 2, 2022
0a9d55f
Temporarily modify path to workflows
danielhollas Dec 2, 2022
2f4cc81
Specify AWB version
danielhollas Dec 2, 2022
4a0f54d
test requirements
danielhollas Dec 2, 2022
83748d9
Revert "Temporarily modify path to workflows"
danielhollas Dec 2, 2022
a062ab1
Fix path
danielhollas Dec 2, 2022
09fa868
Generate jupyter token in GHA
danielhollas Dec 2, 2022
241d5f1
artifact-uploadv2
danielhollas Dec 2, 2022
a2e3358
Disable tests
danielhollas Dec 2, 2022
610b806
Screenshots path
danielhollas Dec 2, 2022
7f01ee5
Bump Selenium version
danielhollas Dec 2, 2022
707fe5f
Fix dependency conflict
danielhollas Dec 2, 2022
1f1e117
Add selenium-enhancer
danielhollas Dec 2, 2022
c24e9a1
Absolute path
danielhollas Dec 2, 2022
306e283
Enable Chrome test
danielhollas Dec 2, 2022
8f0977f
Error out if no screenshots
danielhollas Dec 2, 2022
359330b
Basic tests for other notebooks
danielhollas Dec 2, 2022
bdc02f5
Change path
danielhollas Dec 3, 2022
fc6a885
Remove __init__.py
danielhollas Dec 3, 2022
0b6c8cb
Create screenshot dir explicitly
danielhollas Dec 3, 2022
f7affc7
Screenshot_dir fixture
danielhollas Dec 3, 2022
42caff6
Wait more
danielhollas Dec 3, 2022
8756529
Even more sleep
danielhollas Dec 3, 2022
3b88de6
re-enable workchain install
danielhollas Dec 3, 2022
d797098
Fixes
danielhollas Dec 3, 2022
e6c7a2e
Delete comment
danielhollas Dec 3, 2022
78c9acd
Do not chown
danielhollas Dec 3, 2022
205e0c7
Do not bind mount
danielhollas Dec 3, 2022
0c68bd8
Fix docker-compose file
danielhollas Dec 3, 2022
4627f2b
New approach
danielhollas Dec 3, 2022
4a1dea0
Roll back
danielhollas Dec 3, 2022
de3260a
Switch to localhost temporarily
danielhollas Dec 3, 2022
a00012a
Revert "Do not chown"
danielhollas Dec 3, 2022
5082401
Sleep
danielhollas Dec 3, 2022
eabc152
Run pre-commit in CI
danielhollas Dec 3, 2022
95bbf4e
Disable pre-commit in CI for now
danielhollas Dec 3, 2022
5a2b6f6
Add test
danielhollas Dec 3, 2022
0831229
disable test
danielhollas Dec 3, 2022
1b2ff2b
Download tab
danielhollas Dec 3, 2022
02f6b8d
Download dialog
danielhollas Dec 3, 2022
e82bb8d
Debug
danielhollas Dec 4, 2022
31f5e11
Try different path
danielhollas Dec 4, 2022
20a7133
WTF?
danielhollas Dec 4, 2022
1f38be2
Fix path?
danielhollas Dec 4, 2022
d4ec9ee
Revert "Try different path"
danielhollas Dec 4, 2022
1584935
Better fix
danielhollas Dec 4, 2022
92e7ba2
Run pip check
danielhollas Dec 4, 2022
9ff32a4
Reenable test
danielhollas Dec 4, 2022
b1b0656
Fix
danielhollas Dec 4, 2022
6540e91
refactor conftest
danielhollas Dec 4, 2022
ab4ad2b
cleanup
danielhollas Dec 4, 2022
e76f8ee
fix
danielhollas Dec 4, 2022
1d68c4c
Try fixing pytest cache
danielhollas Dec 4, 2022
f884861
Run post_install test
danielhollas Dec 4, 2022
5bad695
Fix?
danielhollas Dec 4, 2022
9963f33
One more try to fix pytest cache dir
danielhollas Dec 4, 2022
8a1f58b
Switch back to slurm by default
danielhollas Dec 4, 2022
da4a08b
Decrease window width
danielhollas Dec 4, 2022
1bd9da6
Decrease window height
danielhollas Dec 4, 2022
05e546e
Test atmospec image
danielhollas Dec 5, 2022
59b299e
login to ghcr
danielhollas Dec 5, 2022
7f01bd7
Update code plugin traitlet
danielhollas Dec 11, 2022
14d7f1a
test on AWB master
danielhollas Dec 11, 2022
d87569f
selection
danielhollas Dec 12, 2022
b7038c4
debug git path
danielhollas Dec 12, 2022
f5a52a9
fix
danielhollas Dec 12, 2022
f88f125
another approach
danielhollas Dec 12, 2022
69b1c8c
cleanup
danielhollas Dec 12, 2022
cb6bda7
Adjust screenshot path
danielhollas Dec 12, 2022
080ae06
check_first_atom fixture
danielhollas Dec 12, 2022
18a068c
test different conf. generation options
danielhollas Dec 12, 2022
7b913f9
debug
danielhollas Dec 12, 2022
09828d6
image name
danielhollas Dec 12, 2022
9fdb5ee
another try
danielhollas Dec 12, 2022
15b3ae0
Clear textarea
danielhollas Dec 12, 2022
8020288
fix ci
danielhollas Dec 12, 2022
b0ebe8d
more fixes
danielhollas Dec 12, 2022
e748598
Bump AWB version
danielhollas Dec 12, 2022
0eb2f5f
Fix load_code
danielhollas Dec 12, 2022
de6d7da
fix post_install
danielhollas Dec 12, 2022
00ad5a6
Merge branch 'main' into aiida2
danielhollas Dec 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 86 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,110 @@
# Run basic tests for this app on the latest aiidalab-docker image.
# Run basic tests for this app on the latest aiidalab/full-stack docker image.

name: continuous-integration

on:
[push]
[push]

jobs:

# Adapted from: https://github.com/aiidalab/aiidalab-qe
pre-commit:

if: false
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
cache: pip
cache-dependency-path: |
.pre-commit-config.yaml
**/setup.cfg
**/pyproject.toml
**/requirements*.txt

- name: Install dependencies
run: python -m pip install pre-commit~=2.20

- name: Run pre-commit
run: pre-commit run --all-files || ( git status --short; git diff; exit 1 )


test-app:

runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 20
permissions:
packages: read
contents: read

strategy:
matrix:
# For now, we're only targeting latest aiidalab image.
# tag: [ stable, latest ]
tag: [latest]
# Chrome seems to fail fairly often with timeout errors coming from
# the selenium.get_screenshot_as_file()
# ```
# WARNING: Failed to gather screenshot: Message: timeout: Timed out receiving message from renderer: 10.000
# ```
# Googling around, this seems to be a common problem so disabling for now.
# browser: [ chrome, firefox ]
browser: [firefox]
image: ["aiidalab/full-stack", "ghcr.io/ispg-group/atmospec"]
browser: [Firefox, Chrome]
fail-fast: false
env:
IMAGE: ${{ matrix.image }}
TAG: ${{ matrix.tag }}

steps:

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Check out app
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Test app
uses: aiidalab/aiidalab-test-app-action@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
image: aiidalab/aiidalab-docker-stack:${{ matrix.tag }}
browser: ${{ matrix.browser }}
name: aiidalab-ispg
python-version: "3.10"
cache: pip
cache-dependency-path: |
**/setup.cfg
**/pyproject.toml
**/requirements*.txt

- name: Install dependencies for tests
run: pip install -r requirements-test.txt

- name: Set jupyter token env
run: echo "JUPYTER_TOKEN=$(openssl rand -hex 32)" >> $GITHUB_ENV

# The Firefox and its engine geckodrive need do be installed manually to run
# selenium tests.
- name: Install Firefox
if: matrix.browser == 'Firefox'
uses: browser-actions/setup-firefox@latest
with:
firefox-version: "96.0"

- name: Install geckodriver
if: matrix.browser == 'Firefox'
run: |
wget -c https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz
tar xf geckodriver-v0.30.0-linux64.tar.gz -C /usr/local/bin

- name: Run pytest
run: pytest -sv --driver ${{ matrix.browser }} -o cache_dir=$PYTEST_CACHE_DIR

- name: Replace slashes in image name
if: always()
run: echo "IMAGE_NAME=${IMAGE//\//-}" >> $GITHUB_ENV

- name: Upload screenshots as artifacts
uses: actions/upload-artifact@v2
if: always()
uses: actions/upload-artifact@v3
with:
name: Screenshots-${{ matrix.tag }}-${{ matrix.browser }}
path: 'screenshots/'
name: Screenshots-${{env.IMAGE_NAME}}-${{ matrix.tag }}-${{ matrix.browser }}
path: screenshots/
if-no-files-found: error
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ repos:
- id: black
language_version: python3 # Should be a command that runs python3.6+

- repo: https://gitlab.com/pycqa/flake8
- repo: https://github.com/pycqa/flake8
rev: '3.9.2'
hooks:
- id: flake8
Expand Down
7 changes: 0 additions & 7 deletions __init__.py

This file was deleted.

2 changes: 1 addition & 1 deletion aiidalab_ispg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
"ViewSpectrumStep",
]

__version__ = "0.1"
__version__ = "0.2-alpha"
10 changes: 5 additions & 5 deletions aiidalab_ispg/conformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@

from .utils import calc_boltzmann_weights, argsort, KCALtoKJ, EVtoKJ

StructureData = DataFactory("structure")
TrajectoryData = DataFactory("array.trajectory")
StructureData = DataFactory("core.structure")
TrajectoryData = DataFactory("core.array.trajectory")

# xTB cannot be installed automatically in official AiiDAlab Docker images,
# because the dependencies are installed via pip,
Expand Down Expand Up @@ -198,7 +198,7 @@ def _create_trajectory_node(self, conformers, energies):
traj = TrajectoryData(
structurelist=[StructureData(ase=conformer) for conformer in conformers]
)
traj.set_extra("smiles", conformers[0].info["smiles"])
traj.base.extras.set("smiles", conformers[0].info["smiles"])
if energies is not None and len(energies) > 1:
boltzmann_weights = np.array(
calc_boltzmann_weights(energies, T=self._BOLTZMANN_TEMPERATURE)
Expand All @@ -207,8 +207,8 @@ def _create_trajectory_node(self, conformers, energies):
energies = np.array(energies)
traj.set_array("energies", energies)
traj.set_array("boltzmann_weights", boltzmann_weights)
traj.set_extra("energy_units", self._ENERGY_UNITS)
traj.set_extra("temperature", self._BOLTZMANN_TEMPERATURE)
traj.base.extras.set("energy_units", self._ENERGY_UNITS)
traj.base.extras.set("temperature", self._BOLTZMANN_TEMPERATURE)
return traj

# TODO: Automatically filter out conformers with high energy
Expand Down
2 changes: 1 addition & 1 deletion aiidalab_ispg/qeapp/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import ipywidgets as ipw
import traitlets
from aiida.cmdline.utils.query.calculation import CalculationQueryBuilder
from aiida.tools.query.calculation import CalculationQueryBuilder
from aiida.orm import load_node


Expand Down
36 changes: 17 additions & 19 deletions aiidalab_ispg/qeapp/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import ipywidgets as ipw
import traitlets
from aiida.orm import CalcJobNode
from aiida.orm import load_node, CalcJobNode
from aiidalab_widgets_base import register_viewer_widget
from IPython.display import HTML, Javascript, display

Expand Down Expand Up @@ -237,7 +237,7 @@ def _observe_value(self, change):

class CalcJobOutputFollower(traitlets.HasTraits):

calcjob = traitlets.Instance(CalcJobNode, allow_none=True)
calcjob_uuid = traitlets.Unicode(allow_none=True)
filename = traitlets.Unicode(allow_none=True)
output = traitlets.List(trait=traitlets.Unicode)
lineno = traitlets.Int()
Expand All @@ -253,14 +253,11 @@ def __init__(self, **kwargs):

super().__init__(**kwargs)

@traitlets.observe("calcjob")
@traitlets.observe("calcjob_uuid")
def _observe_calcjob(self, change):
try:
if change["old"].pk == change["new"].pk:
# Old and new process are identical.
return
except AttributeError:
pass
calcjob_uuid = change["new"]
if change["old"] == calcjob_uuid:
return

with self._lock:
# Stop following
Expand All @@ -278,30 +275,30 @@ def _observe_calcjob(self, change):
# (Re/)start following
if change["new"]:
self._follow_output_thread = Thread(
target=self._follow_output, args=(change["new"],)
target=self._follow_output, args=(calcjob_uuid,)
)
self._follow_output_thread.start()

def _follow_output(self, calcjob):
def _follow_output(self, calcjob_uuid):
"""Monitor calcjob and orchestrate pushing and pulling of output."""
self._pull_thread = Thread(target=self._pull_output, args=(calcjob,))
self._pull_thread = Thread(target=self._pull_output)
self._pull_thread.start()
self._push_thread = Thread(target=self._push_output, args=(calcjob,))
self._push_thread = Thread(target=self._push_output, args=(calcjob_uuid,))
self._push_thread.start()

def _fetch_output(self, calcjob):
assert isinstance(calcjob, CalcJobNode)
if "retrieved" in calcjob.outputs:
try:
self.filename = calcjob.attributes["output_filename"]
with calcjob.outputs.retrieved.open(self.filename) as f:
self.filename = calcjob.base.attributes.get("output_filename")
with calcjob.outputs.retrieved.base.repository.open(self.filename) as f:
return f.read().splitlines()
except OSError:
return list()

elif "remote_folder" in calcjob.outputs:
try:
fn_out = calcjob.attributes["output_filename"]
fn_out = calcjob.base.attributes.get("output_filename")
self.filename = fn_out
with NamedTemporaryFile() as tmpfile:
calcjob.outputs.remote_folder.getfile(fn_out, tmpfile.name)
Expand All @@ -313,9 +310,10 @@ def _fetch_output(self, calcjob):

_EOF = None

def _push_output(self, calcjob, delay=0.2):
def _push_output(self, calcjob_uuid, delay=0.2):
"""Push new log lines onto the queue."""
lineno = 0
calcjob = load_node(calcjob_uuid)
while True:
try:
lines = self._fetch_output(calcjob)
Expand All @@ -330,7 +328,7 @@ def _push_output(self, calcjob, delay=0.2):
self._output_queue.put(self._EOF)
break # noqa: B012

def _pull_output(self, calcjob):
def _pull_output(self):
"""Pull new log lines from the queue and update traitlets."""
while True:
item = self._output_queue.get()
Expand All @@ -351,8 +349,8 @@ def __init__(self, calcjob, **kwargs):
self.output_follower = CalcJobOutputFollower()
self.log_output = LogOutputWidget()

self.output_follower.calcjob_uuid = self.calcjob.uuid
self.output_follower.observe(self._observe_output_follower_lineno, ["lineno"])
self.output_follower.calcjob = self.calcjob

super().__init__(
[ipw.HTML(f"CalcJob: {self.calcjob}"), self.log_output], **kwargs
Expand Down
28 changes: 16 additions & 12 deletions aiidalab_ispg/spectrum.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Widget for displaying UV/VIS spectra in an interactive graph.
"""Calculating NEA UV/vis spectra and displaying them in an interactive plot.

Authors:
* Daniel Hollas <daniel.hollas@bristol.ac.uk>
Expand All @@ -9,7 +9,7 @@
from scipy import constants
import numpy as np

from aiida.orm import QueryBuilder
from aiida.orm import load_node, QueryBuilder
from aiida.plugins import DataFactory

# https://docs.bokeh.org/en/latest/docs/user_guide/jupyter.html
Expand All @@ -22,9 +22,9 @@

# https://docs.bokeh.org/en/latest/docs/reference/io.html#bokeh.io.output_notebook
output_notebook(hide_banner=True, load_timeout=5000, verbose=True)
XyData = DataFactory("array.xy")
StructureData = DataFactory("structure")
TrajectoryData = DataFactory("array.trajectory")
XyData = DataFactory("core.array.xy")
StructureData = DataFactory("core.structure")
TrajectoryData = DataFactory("core.array.trajectory")


@unique
Expand All @@ -48,6 +48,7 @@ class BokehFigureContext(ipw.Output):
def __init__(self, fig):
super().__init__()
self._figure = fig
self._handle = None
self.on_displayed(lambda x: x.set_handle())

def set_handle(self):
Expand All @@ -62,7 +63,8 @@ def get_figure(self):
return self._figure

def update(self):
push_notebook(handle=self._handle)
if self._handle is not None:
push_notebook(handle=self._handle)


class Spectrum(object):
Expand Down Expand Up @@ -188,7 +190,7 @@ class SpectrumWidget(ipw.VBox):
# We use SMILES to find matching experimental spectra
# that are possibly stored in our DB as XyData.
smiles = traitlets.Unicode(allow_none=True)
experimental_spectrum = traitlets.Instance(XyData, allow_none=True)
experimental_spectrum_uuid = traitlets.Unicode(allow_none=True)

# For now, we do not allow different intensity units
intensity_unit = "cm^2 per molecule"
Expand Down Expand Up @@ -428,9 +430,10 @@ def _handle_energy_unit_update(self, change):
kernel=self.kernel_selector.value,
energy_unit=energy_unit,
)
if self.experimental_spectrum is not None:
if self.experimental_spectrum_uuid is not None:
node = load_node(self.experimental_spectrum_uuid)
self._plot_experimental_spectrum(
spectrum_node=self.experimental_spectrum, energy_unit=energy_unit
spectrum_node=node, energy_unit=energy_unit
)

def _unhighlight_conformer(self):
Expand Down Expand Up @@ -622,7 +625,7 @@ def reset(self):
self.conformer_transitions = None
self.conformer_structures = None
self.smiles = None
self.experimental_spectrum = None
self.experimental_spectrum_uuid = None

self.disable_controls()
self.clean_figure()
Expand Down Expand Up @@ -701,9 +704,10 @@ def _find_experimental_spectrum(self, smiles: str):
# TODO: For now let's just assume we have one
# canonical experimental spectrum per compound.
# for spectrum in qb.iterall():
self.experimental_spectrum = qb.first()[0]
experimental_spectrum_node = qb.first()[0]
self.experimental_spectrum_uuid = experimental_spectrum_node.uuid
self._plot_experimental_spectrum(
spectrum_node=self.experimental_spectrum,
spectrum_node=experimental_spectrum_node,
energy_unit=self.energy_unit_selector.value,
)

Expand Down
Loading