diff --git a/README.md b/README.md index e6f01033..9a4a8346 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ The information also features a distribution diagram of licenses and a brief des A risk assessment tool which simulates the airborne spread of the SARS-CoV-2 virus for space managers. -### CAiMIRA Expert App +### CAiMIRA Expert App and CO₂ App A tool to interact with various parameters of the CAiMIRA model. @@ -139,13 +139,32 @@ If any of the `.rst` files under the `caimira/docs` folder is changed, this comm Then, right click on `caimira/docs/_build/html/index.html` and select `Open with` your preferred web browser. -### Running the CAiMIRA Expert-App app in development mode +### Running the CAiMIRA Expert-App or CO2-App apps in development mode + +#### Disclaimer + +The `ExpertApplication` and `CO2Application` are no longer actively maintained but will remain in the codebase for legacy purposes. +Please note that the functionality of these applications might be compromised due to deprecation issues. + +#### Running the Applications + +These applications only work within Jupyter notebooks. Attempting to run them outside of a Jupyter environment may result in errors or degraded functionality. + +##### Prerequisites + +Make sure you have the needed dependencies intalled: ``` -voila caimira/apps/expert/caimira.ipynb --port=8080 +pip install notebook jupyterlab ``` -Then visit http://localhost:8080. +Running with Visual Studio Code (VSCode): + +1. Ensure you have the following extensions installed in VSCode: `Jupyter` and `Python`. + +2. Open VSCode and navigate to the directory containing the notebook. + +3. Open the notebook (e.g. `caimira/apps/expert/caimira.ipynb`) and run the cells by clicking the `run` button next to each cell. ### Running the tests diff --git a/app-config/caimira-public-docker-image/Dockerfile b/app-config/caimira-public-docker-image/Dockerfile index 6e2c6914..621f344e 100644 --- a/app-config/caimira-public-docker-image/Dockerfile +++ b/app-config/caimira-public-docker-image/Dockerfile @@ -14,8 +14,6 @@ COPY ./app-config/caimira-public-docker-image/run_caimira.sh /opt/caimira/start. # To ensure that we have installed the full requirements, re-run the pip install. # In the best case this will be a no-op. RUN cd /opt/caimira/src/ && /opt/caimira/app/bin/pip install -r /opt/caimira/src/requirements.txt -RUN /opt/caimira/app/bin/jupyter trust /opt/caimira/src/caimira/apps/expert/*.ipynb -RUN /opt/caimira/app/bin/jupyter trust /opt/caimira/src/caimira/apps/expert_co2/*.ipynb COPY ./app-config/caimira-public-docker-image/nginx.conf /opt/caimira/nginx.conf EXPOSE 8080 diff --git a/app-config/caimira-public-docker-image/nginx.conf b/app-config/caimira-public-docker-image/nginx.conf index dd9595d9..d24c4399 100644 --- a/app-config/caimira-public-docker-image/nginx.conf +++ b/app-config/caimira-public-docker-image/nginx.conf @@ -44,18 +44,6 @@ http { large_client_header_buffers 4 16k; - location /voila-server/ { - proxy_pass http://localhost:8082/voila-server/; - } - rewrite ^/expert-app$ /voila-server/ last; - rewrite ^/(files/static)/(.*)$ /voila-server/voila/$1/$2 last; - - location /co2-voila-server/ { - proxy_pass http://localhost:8083/co2-voila-server/; - } - rewrite ^/co2-app$ /voila-server/ last; - rewrite ^/(files/static)/(.*)$ /voila-server/voila/$1/$2 last; - location / { proxy_pass http://localhost:8081; } diff --git a/app-config/caimira-public-docker-image/run_caimira.sh b/app-config/caimira-public-docker-image/run_caimira.sh index 5f12ca46..00a61542 100755 --- a/app-config/caimira-public-docker-image/run_caimira.sh +++ b/app-config/caimira-public-docker-image/run_caimira.sh @@ -5,17 +5,6 @@ echo 'Please see https://gitlab.cern.ch/caimira/caimira for terms of use.' # Run a proxy for the apps (listening on 8080). nginx -c /opt/caimira/nginx.conf -# Run the expert app in the background. cd /opt/caimira/src/caimira -/opt/caimira/app/bin/python -m voila /opt/caimira/src/caimira/apps/expert/caimira.ipynb \ - --port=8082 --no-browser --base_url=/voila-server/ \ - --Voila.tornado_settings 'allow_origin=*' \ - >> /var/log/expert-app.log 2>&1 & - -/opt/caimira/app/bin/python -m voila /opt/caimira/src/caimira/apps/expert_co2/caimira.ipynb \ - --port=8083 --no-browser --base_url=/co2-voila-server/ \ - --Voila.tornado_settings 'allow_origin=*' \ - >> /var/log/co2-app.log 2>&1 & - # Run the calculator in the foreground. /opt/caimira/app/bin/python -m caimira.apps.calculator --port 8081 --no-debug diff --git a/app-config/calculator-app/app.sh b/app-config/calculator-app/app.sh index 505067b7..f3a05bd7 100755 --- a/app-config/calculator-app/app.sh +++ b/app-config/calculator-app/app.sh @@ -28,12 +28,7 @@ if [[ "$APP_NAME" == "calculator-app" ]]; then echo "Starting the caimira webservice with: python -m caimira.apps.calculator ${args[@]}" python -m caimira.apps.calculator "${args[@]}" -elif [[ "$APP_NAME" == "caimira-voila" ]]; then - echo "Starting the voila service" - voila caimira/apps/expert/ --port=8080 --no-browser --base_url=/voila-server/ --tornado_settings 'allow_origin=*' -elif [[ "$APP_NAME" == "caimira-co2-voila" ]]; then - echo "Starting the CO2 voila service" - voila caimira/apps/expert_co2/ --port=8080 --no-browser --base_url=/co2-voila-server/ --tornado_settings 'allow_origin=*' + else echo "No APP_NAME specified" exit 1 diff --git a/app-config/docker-compose.yml b/app-config/docker-compose.yml index 2d41dcc1..b44ba2dd 100644 --- a/app-config/docker-compose.yml +++ b/app-config/docker-compose.yml @@ -1,16 +1,5 @@ version: "3.8" services: - expert-app: - image: calculator-app - environment: - - APP_NAME=caimira-voila - user: ${CURRENT_UID:?"Please run as follows 'CURRENT_UID=$(id -u):$(id -g) docker-compose up'"} - - expert-co2-app: - image: calculator-app - environment: - - APP_NAME=caimira-co2-voila - user: ${CURRENT_UID:?"Please run as follows 'CURRENT_UID=$(id -u):$(id -g) docker-compose up'"} calculator-app: image: calculator-app @@ -54,10 +43,6 @@ services: condition: service_started calculator-open-app: condition: service_started - expert-app: - condition: service_started - expert-co2-app: - condition: service_started auth-service: condition: service_started user: ${CURRENT_UID} diff --git a/app-config/nginx/nginx.conf b/app-config/nginx/nginx.conf index 5e0ed708..3b447fe9 100644 --- a/app-config/nginx/nginx.conf +++ b/app-config/nginx/nginx.conf @@ -73,44 +73,8 @@ http { proxy_pass http://calculator-app:8080/$request_uri; } - location /voila-server/ { - proxy_intercept_errors on; - - # Anything under voila-server or expert-app is authenticated. - auth_request /auth/probe; - error_page 401 = @error401; - error_page 404 = @proxy_404_error_handler; - - # expert-app is the name of the voila server in each of docker-compose, - # caimira-test.web.cern.ch and caimira.web.cern.ch. - proxy_pass http://expert-app:8080/voila-server/; - } - rewrite ^/expert-app$ /voila-server/voila/render/caimira.ipynb last; - rewrite ^/(files/static)/(.*)$ /voila-server/voila/$1/$2 last; - - # Before implementing the nginx router we could access /voila/render/caimira.ipynb. - # Redirect this (and all other) URLs to the new scheme. + # Redirect URLs to the new scheme. absolute_redirect off; - rewrite ^/voila/(.*)$ /voila-server/voila/$1 redirect; - - location /co2-voila-server/ { - proxy_intercept_errors on; - - # Anything under voila-server or co2-app is authenticated. - auth_request /auth/probe; - error_page 401 = @error401; - error_page 404 = @proxy_404_error_handler; - - # expert-co2-app is the name of the voila server in each of docker-compose, - # caimira-test.web.cern.ch and caimira.web.cern.ch. - proxy_pass http://expert-co2-app:8080/co2-voila-server/; - } - rewrite ^/co2-app$ /co2-voila-server/voila/render/caimira.ipynb last; - rewrite ^/(files/static)/(.*)$ /co2-voila-server/voila/$1/$2 last; - - # Before implementing the nginx router we could access /voila/render/caimira.ipynb. - # Redirect this (and all other) URLs to the new scheme. - rewrite ^/voila/(.*)$ /co2-voila-server/voila/$1 redirect; location / { # By default we have no authentication. diff --git a/app-config/openshift/deploymentconfig.yaml b/app-config/openshift/deploymentconfig.yaml index 82d8974b..ca2f363f 100644 --- a/app-config/openshift/deploymentconfig.yaml +++ b/app-config/openshift/deploymentconfig.yaml @@ -68,120 +68,6 @@ kind: ImageStreamTag name: 'auth-service:latest' namespace: ${PROJECT_NAME} - - - apiVersion: apps.openshift.io/v1 - kind: DeploymentConfig - metadata: - name: expert-app - labels: {app: expert-app} - spec: - replicas: 1 - template: - metadata: - labels: - app: expert-app - spec: - containers: - - name: calculator-app - env: - - name: APP_NAME - value: caimira-voila - image: '${PROJECT_NAME}/calculator-app' - ports: - - containerPort: 8080 - protocol: TCP - imagePullPolicy: Always - resources: - limits: { cpu: '1', memory: 1Gi } - requests: { cpu: 1m, memory: 512Mi } - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - dnsPolicy: ClusterFirst - restartPolicy: Always - schedulerName: default-scheduler - securityContext: { } - terminationGracePeriodSeconds: 30 - strategy: - activeDeadlineSeconds: 21600 - resources: { } - rollingParams: - intervalSeconds: 1 - maxSurge: 25% - maxUnavailable: 25% - timeoutSeconds: 600 - updatePeriodSeconds: 1 - type: Rolling - test: false - selector: - app: expert-app - triggers: - - type: ConfigChange - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - calculator-app - from: - kind: ImageStreamTag - name: 'calculator-app:latest' - namespace: ${PROJECT_NAME} - - - apiVersion: apps.openshift.io/v1 - kind: DeploymentConfig - metadata: - name: expert-co2-app - labels: {app: expert-co2-app} - spec: - replicas: 1 - template: - metadata: - labels: - app: expert-co2-app - spec: - containers: - - name: calculator-app - env: - - name: APP_NAME - value: caimira-co2-voila - image: '${PROJECT_NAME}/calculator-app' - ports: - - containerPort: 8080 - protocol: TCP - imagePullPolicy: Always - resources: - limits: { cpu: '1', memory: 1Gi } - requests: { cpu: 1m, memory: 512Mi } - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - dnsPolicy: ClusterFirst - restartPolicy: Always - schedulerName: default-scheduler - securityContext: { } - terminationGracePeriodSeconds: 30 - strategy: - activeDeadlineSeconds: 21600 - resources: { } - rollingParams: - intervalSeconds: 1 - maxSurge: 25% - maxUnavailable: 25% - timeoutSeconds: 600 - updatePeriodSeconds: 1 - type: Rolling - test: false - selector: - app: expert-co2-app - triggers: - - type: ConfigChange - - type: ImageChange - imageChangeParams: - automatic: true - containerNames: - - calculator-app - from: - kind: ImageStreamTag - name: 'calculator-app:latest' - namespace: ${PROJECT_NAME} - apiVersion: apps.openshift.io/v1 kind: DeploymentConfig diff --git a/app-config/openshift/services.yaml b/app-config/openshift/services.yaml index f32ba062..78a05dfe 100644 --- a/app-config/openshift/services.yaml +++ b/app-config/openshift/services.yaml @@ -27,40 +27,6 @@ deploymentconfig: auth-service sessionAffinity: 'None' type: 'ClusterIP' - - - apiVersion: v1 - kind: Service - metadata: - labels: - app: expert-app - name: expert-app - spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - deploymentconfig: expert-app - sessionAffinity: 'None' - type: 'ClusterIP' - - - apiVersion: v1 - kind: Service - metadata: - labels: - app: expert-co2-app - name: expert-co2-app - spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - deploymentconfig: expert-co2-app - sessionAffinity: 'None' - type: 'ClusterIP' - apiVersion: v1 kind: Service diff --git a/caimira/apps/calculator/__init__.py b/caimira/apps/calculator/__init__.py index 585e271c..abe9bda7 100644 --- a/caimira/apps/calculator/__init__.py +++ b/caimira/apps/calculator/__init__.py @@ -42,7 +42,7 @@ from .user import AuthenticatedUser, AnonymousUser # calculator version. If the calculator needs to make breaking changes (e.g. change # form attributes) then it can also increase its MAJOR version without needing to # increase the overall CAiMIRA version (found at ``caimira.__version__``). -__version__ = "4.15.3" +__version__ = "4.16.0" LOG = logging.getLogger("Calculator") @@ -517,6 +517,9 @@ def make_app( (get_root_calculator_url(r'/user-guide'), GenericExtraPage, { 'active_page': 'calculator/user-guide', 'filename': 'userguide.html.j2'}), + (get_root_url(r'/expert-app'), GenericExtraPage, { + 'active_page': 'expert-app', + 'filename': 'expert-app.html.j2'}), ] profiler_enabled = int(os.environ.get('CAIMIRA_PROFILER_ENABLED', 0)) diff --git a/caimira/apps/expert.py b/caimira/apps/expert.py index 111505d2..79c64c2b 100644 --- a/caimira/apps/expert.py +++ b/caimira/apps/expert.py @@ -12,10 +12,13 @@ from matplotlib import pyplot as plt import numpy as np import datetime import pandas as pd +import logging from caimira import data, models, state from caimira.store.data_registry import DataRegistry +LOG = logging.getLogger(__name__) + def collapsible(widgets_to_collapse: typing.List, title: str, start_collapsed=False): collapsed = widgets.Accordion([widgets.VBox(widgets_to_collapse)]) @@ -929,6 +932,10 @@ class CAIMIRAStateBuilder(state.StateBuilder): class ExpertApplication(Controller): def __init__(self) -> None: + LOG.warning( + "ExpertApplication is currently deactivated and will no longer be maintained. It remains in the codebase for legacy purposes." + ) + self._data_registry = DataRegistry() #: A list of scenario name and ModelState instances. This is intended to be #: mutated. Any mutation should notify the appropriate Views for handling. diff --git a/caimira/apps/expert_co2.py b/caimira/apps/expert_co2.py index d083d20b..29964bf9 100644 --- a/caimira/apps/expert_co2.py +++ b/caimira/apps/expert_co2.py @@ -2,6 +2,7 @@ import dataclasses import ipywidgets as widgets import typing import numpy as np +import logging from caimira import data, models, state from caimira.store.data_registry import DataRegistry @@ -11,6 +12,8 @@ import matplotlib.lines as mlines import matplotlib.patches as patches from .expert import generate_presence_widget, collapsible, ipympl_canvas, WidgetGroup, CAIMIRAStateBuilder +LOG = logging.getLogger(__name__) + def baseline_model(data_registry: DataRegistry): return models.CO2ConcentrationModel( @@ -188,6 +191,10 @@ class ExposureComparisonResult(View): class CO2Application(Controller): def __init__(self) -> None: + LOG.warning( + "CO2Application is currently deactivated and will no longer be maintained. It remains in the codebase for legacy purposes." + ) + self._data_registry = DataRegistry() # self._debug_output = widgets.Output() diff --git a/caimira/apps/templates/about.html.j2 b/caimira/apps/templates/about.html.j2 index 28140cc1..c503c1bb 100644 --- a/caimira/apps/templates/about.html.j2 +++ b/caimira/apps/templates/about.html.j2 @@ -15,7 +15,7 @@ CAiMIRA stands for CERN Airborne Model for Indoor Risk Assessment, previously kn Since then, the model has evolved and now is capable of simulating the short-range component. CAiMIRA comes with different applications that allow more or less flexibility in the input parameters: The mathematical and physical model simulate the airborne spread of SARS-CoV-2 virus in a finite volume, assuming a homogenous mixture and a two-stage exhaled jet model, and estimates the risk of COVID-19 airborne transmission therein. The results DO NOT include other known modes of SARS-CoV-2 transmission. Hence, the output from this model is only valid when the other recommended public health & safety instructions are observed, such as good hand hygiene and other barrier measures.
diff --git a/caimira/apps/templates/base/index.html.j2 b/caimira/apps/templates/base/index.html.j2 index 65f19037..d7c432a3 100644 --- a/caimira/apps/templates/base/index.html.j2 +++ b/caimira/apps/templates/base/index.html.j2 @@ -32,7 +32,7 @@
Calculator

-
Expert app
+
Expert app

@@ -46,7 +46,7 @@

Applications

-
CAiMIRA is composed of two applications, the Calculator and the Expert App.
+
CAiMIRA is composed of two applications, the Calculator and the Expert App.

About

diff --git a/caimira/apps/templates/base/layout.html.j2 b/caimira/apps/templates/base/layout.html.j2 index 5ea37537..e64664bd 100644 --- a/caimira/apps/templates/base/layout.html.j2 +++ b/caimira/apps/templates/base/layout.html.j2 @@ -45,8 +45,8 @@
diff --git a/caimira/apps/templates/expert-app.html.j2 b/caimira/apps/templates/expert-app.html.j2 new file mode 100644 index 00000000..5e18a638 --- /dev/null +++ b/caimira/apps/templates/expert-app.html.j2 @@ -0,0 +1,18 @@ +{% extends "base/layout.html.j2" %} + +{% block main %} + +
+ +

CAiMIRA Expert Apps currently deactivated


+ +With the latest feature implementations in the core CAiMIRA engine, the ExpertApplication and CO2Application apps are no longer actively maintained. +For legacy purposes, the source code is still available in the GitLab repository. +

+For any query, please let us know by sending an email to CAiMIRA-dev@cern.ch. +

+ + +
+ +{% endblock main %} \ No newline at end of file diff --git a/caimira/tests/apps/test_expert_app.py b/caimira/tests/apps/test_expert_app.py index c94f8206..d320f073 100644 --- a/caimira/tests/apps/test_expert_app.py +++ b/caimira/tests/apps/test_expert_app.py @@ -8,6 +8,7 @@ def expert_app(): return caimira.apps.ExpertApplication() +@pytest.mark.skip(reason="ExpertApplication is deactivated") def test_app(expert_app): # To start with, let's just test that the application runs. We don't try to # do anything fancy to verify how it looks etc., we leave that for manual @@ -15,6 +16,7 @@ def test_app(expert_app): assert expert_app._model_scenarios[0][0] == "Scenario 1" +@pytest.mark.skip(reason="ExpertApplication is deactivated") def test_new_scenario_changes_tab(expert_app): # Adding a new scenario should change the tab index of the multi-model view. assert expert_app.multi_model_view.widget.selected_index == 0 diff --git a/requirements.txt b/requirements.txt index 452741d2..6adbfedf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -49,16 +49,6 @@ json5==0.9.14 jsonpointer==2.4 jsonschema==4.21.1 jsonschema-specifications==2023.12.1 -jupyter_client==8.6.0 -jupyter_core==5.7.1 -jupyter-events==0.9.0 -jupyter-lsp==2.2.2 -jupyter_server==2.12.5 -jupyter_server_terminals==0.5.2 -jupyterlab==4.1.1 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.25.3 -jupyterlab-widgets==1.1.7 kiwisolver==1.4.5 loky==3.4.1 MarkupSafe==2.1.5 @@ -124,7 +114,6 @@ typing_extensions==4.9.0 tzdata==2024.1 uri-template==1.3.0 urllib3==2.2.0 -voila==0.5.5 wcwidth==0.2.13 webcolors==1.13 webencodings==0.5.1 diff --git a/setup.py b/setup.py index 62e6f5ef..42954280 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,6 @@ REQUIREMENTS: dict = { 'timezonefinder', 'tornado', 'types-retry', - 'voila', ], 'app': [], 'test': [ @@ -54,7 +53,6 @@ REQUIREMENTS: dict = { 'types-requests', ], 'dev': [ - 'jupyterlab', ], 'doc': [ 'sphinx',