├── .flake8 ├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .prettierrc.js ├── .travis.yml ├── LICENSE ├── MANIFEST.in ├── NOTICE ├── README.md ├── app ├── .eslintignore ├── .eslintrc.js ├── babel.config.js ├── dist │ ├── fonts │ │ ├── MaterialIcons-Regular.0509ab09.woff2 │ │ ├── MaterialIcons-Regular.29b882f0.woff │ │ ├── MaterialIcons-Regular.96c47680.eot │ │ └── MaterialIcons-Regular.da4ea5cd.ttf │ ├── index.html │ └── js │ │ ├── app.js │ │ ├── app.js.map │ │ ├── chunk-vendors.js │ │ └── chunk-vendors.js.map ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── components │ │ ├── App.vue │ │ ├── CCT.vue │ │ ├── Summary.vue │ │ ├── SuperGraph.vue │ │ ├── SuperGraphEnsemble.vue │ │ ├── boxplot │ │ │ ├── box.vue │ │ │ ├── markers.vue │ │ │ ├── outlier.vue │ │ │ ├── statistics.vue │ │ │ └── tooltip.vue │ │ ├── callsiteCorrespondence │ │ │ ├── boxplot.vue │ │ │ └── index_cc.vue │ │ ├── callsiteInformation │ │ │ ├── boxplot.vue │ │ │ └── index_ci.vue │ │ ├── ensembleHistogram │ │ │ ├── index_eh.vue │ │ │ └── tooltip.vue │ │ ├── ensembleScatterplot │ │ │ ├── index_es.vue │ │ │ └── tooltip.vue │ │ ├── general │ │ │ ├── colormap.vue │ │ │ ├── footer.vue │ │ │ ├── infoChip.vue │ │ │ ├── loader.vue │ │ │ ├── runSelection.vue │ │ │ ├── settings │ │ │ │ ├── header.vue │ │ │ │ ├── index.vue │ │ │ │ └── select.vue │ │ │ ├── splitControl.vue │ │ │ ├── toolbar.vue │ │ │ └── viewSelection.vue │ │ ├── gradientView │ │ │ └── index_gv.vue │ │ ├── moduleHierarchy │ │ │ ├── index.vue │ │ │ ├── lib │ │ │ │ ├── comparator.js │ │ │ │ ├── edge.js │ │ │ │ ├── graph.js │ │ │ │ ├── linkedList.js │ │ │ │ ├── linkedListNode.js │ │ │ │ ├── node.js │ │ │ │ └── queue.js │ │ │ └── tooltip.vue │ │ ├── nodeLink │ │ │ ├── d3-inputbox.js │ │ │ ├── index_nl.vue │ │ │ └── tooltip.vue │ │ ├── parameterProjection │ │ │ └── index_pp.vue │ │ ├── sankey │ │ │ ├── edges.vue │ │ │ ├── encodings │ │ │ │ ├── guides.vue │ │ │ │ ├── mean.vue │ │ │ │ ├── meanDiff.vue │ │ │ │ ├── meanGradients.vue │ │ │ │ ├── rankDiff.vue │ │ │ │ ├── targetLine.vue │ │ │ │ └── tooltip.vue │ │ │ ├── index_sg.vue │ │ │ ├── lib │ │ │ │ ├── bfs.js │ │ │ │ ├── detectcycle.js │ │ │ │ ├── dfs.js │ │ │ │ └── sankey.js │ │ │ ├── miniHistograms.vue │ │ │ └── nodes.vue │ │ ├── singleHistogram │ │ │ ├── index_sh.vue │ │ │ └── tooltip.vue │ │ ├── singleScatterplot │ │ │ └── index_ss.vue │ │ └── summary │ │ │ ├── config.vue │ │ │ ├── moduleMap.vue │ │ │ ├── profile.vue │ │ │ └── timeSeries.vue │ ├── lib │ │ ├── color │ │ │ ├── COLORS.js │ │ │ └── index.js │ │ ├── interactions │ │ │ ├── lasso.js │ │ │ └── spin.js │ │ ├── package.json │ │ ├── routing │ │ │ ├── APIService.js │ │ │ └── EventHandler.js │ │ ├── utils.js │ │ └── views │ │ │ ├── boxPlot.js │ │ │ ├── hist_view.js │ │ │ ├── histogram.js │ │ │ └── matrixLayout.js │ ├── main.js │ └── store.js ├── update_build.sh └── vue.config.js ├── callflow ├── .pylintrc ├── __init__.py ├── algorithms │ ├── __init__.py │ ├── bland_altman.py │ ├── deltacon_similarity.py │ ├── k_medoids.py │ ├── prog_kmeans.py │ └── wl_distance.py ├── datastructures │ ├── __init__.py │ ├── ensemblegraph.py │ ├── metrics.py │ └── supergraph.py ├── layout │ ├── __init__.py │ ├── hierarchy.py │ ├── node_link.py │ └── sankey.py ├── modules │ ├── __init__.py │ ├── boxplot.py │ ├── diff_view.py │ ├── gradients.py │ ├── histogram.py │ ├── parameter_projection.py │ └── scatterplot.py ├── operations │ ├── __init__.py │ ├── config.py │ ├── filter.py │ ├── group.py │ ├── regex_module_matcher.py │ ├── split_callee.py │ ├── split_entry.py │ └── unify.py ├── tests │ └── executable.py ├── utils │ ├── __init__.py │ ├── argparser.py │ ├── df.py │ ├── logger.py │ ├── nxg.py │ ├── sanitizer.py │ ├── timer.py │ └── utils.py └── version.py ├── data ├── README.md ├── caliper-lulesh-cali │ └── lulesh-annotation-profile.cali ├── caliper-lulesh-json │ └── lulesh-sample-annotation-profile.json ├── caliper-simple-cali │ └── caliper-simple.cali ├── caliper-simple-json │ └── caliper-simple.json ├── hpctoolkit-allgather-database │ ├── 1.osu_allgather-000000-000-a8c00471-152577-0.metric-db │ ├── 1.osu_allgather-000000-001-a8c00471-152577-0.metric-db │ ├── 1.osu_allgather-000001-000-a8c00471-152578-0.metric-db │ ├── 1.osu_allgather-000001-001-a8c00471-152578-0.metric-db │ ├── 1.osu_allgather-000002-000-a8c00471-152579-0.metric-db │ ├── 1.osu_allgather-000002-001-a8c00471-152579-0.metric-db │ ├── 1.osu_allgather-000003-000-a8c00471-152580-0.metric-db │ ├── 1.osu_allgather-000003-001-a8c00471-152580-0.metric-db │ ├── 1.osu_allgather-000004-000-a8c00471-152581-0.metric-db │ ├── 1.osu_allgather-000004-001-a8c00471-152581-0.metric-db │ ├── 1.osu_allgather-000005-000-a8c00471-152582-0.metric-db │ ├── 1.osu_allgather-000005-001-a8c00471-152582-0.metric-db │ ├── 1.osu_allgather-000006-000-a8c00471-152583-0.metric-db │ ├── 1.osu_allgather-000006-001-a8c00471-152583-0.metric-db │ ├── 1.osu_allgather-000007-000-a8c00471-152584-0.metric-db │ ├── 1.osu_allgather-000007-001-a8c00471-152584-0.metric-db │ ├── 1.osu_allgather-000008-000-a8c00471-152585-0.metric-db │ ├── 1.osu_allgather-000008-001-a8c00471-152585-0.metric-db │ ├── 1.osu_allgather-000009-000-a8c00471-152586-0.metric-db │ ├── 1.osu_allgather-000009-001-a8c00471-152586-0.metric-db │ ├── experiment.xml │ └── src │ │ └── osu_allgather.c └── hpctoolkit-cpi-database │ ├── 1.cpi-000000-000-a8c00270-160443-0.metric-db │ ├── 1.cpi-000001-000-a8c00270-160444-0.metric-db │ ├── 1.cpi-000002-000-a8c00270-160445-0.metric-db │ ├── 1.cpi-000003-000-a8c00270-160446-0.metric-db │ ├── experiment.xml │ └── src │ └── cpi.c ├── docs ├── Makefile ├── conf.py ├── examples │ └── callflow.config.json ├── figures │ └── CallFlow-basic-architecture.png ├── getting_started.rst ├── index.rst └── user_guide.rst ├── examples ├── %callflow-ipython-magic.ipynb ├── CallFlow-python-interface-demo.ipynb └── CallFlow-v1.1-python-interface-demo.ipynb ├── experiments └── cycle_issue ├── pyproject.toml ├── pytest.ini ├── requirements.txt ├── server ├── __init__.py ├── main.py ├── notebook_server.py ├── provider_api.py └── provider_base.py └── setup.py /.flake8: -------------------------------------------------------------------------------- 1 | # -*- conf -*- 2 | # flake8 settings for callflow 3 | 4 | [flake8] 5 | ignore = E203, E266, E501, W503, E731 6 | # line length is intentionally set to 80 here because black uses Bugbear 7 | # See https://github.com/psf/black/blob/master/README.md#line-length for more details 8 | max-line-length = 80 9 | max-complexity = 18 10 | select = B,C,E,F,W,T4,B9 11 | # We need to configure the mypy.ini because the flake8-mypy's default 12 | # options don't properly override it, so if we don't specify it we get 13 | # half of the config from mypy.ini and half from flake8-mypy. 14 | mypy_config = mypy.inik 15 | -------------------------------------------------------------------------------- /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python application 5 | 6 | on: 7 | push: 8 | branches: [ develop ] 9 | pull_request: 10 | branches: [ develop ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up Python 3.8 20 | uses: actions/setup-python@v2 21 | with: 22 | python-version: 3.8 23 | 24 | - uses: actions/cache@v2 25 | with: 26 | path: ~/.cache/pip 27 | key: ${{ hashFiles('setup.py') }}-${{ hashFiles('dev-requirements.txt') }} 28 | 29 | - uses: actions/cache@v2 30 | with: 31 | path: ${{ env.pythonLocation }} 32 | key: ${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ hashFiles('requirements.txt') }} 33 | 34 | - name: Install dependencies 35 | run: | 36 | python -m pip install --upgrade pip 37 | pip install flake8 pytest black 38 | # if [ -f requirements.txt ]; then pip install --upgrade 39 | # --upgrade-strategy eager -r requirements.txt -e .; fi 40 | 41 | - name: Check installation 42 | run: | 43 | python setup.py install 44 | npm install --prefix=app 45 | which callflow 46 | 47 | - name: Black check 48 | run: | 49 | black --diff --check . 50 | 51 | - name: Lint with flake8 52 | run: | 53 | # stop the build if there are Python syntax errors or undefined names 54 | flake8 . --count --show-source --statistics --exclude=examples 55 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 56 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 57 | 58 | - name: Lint with npm 59 | run: | 60 | npm run lint --prefix=app 61 | 62 | - name: Test with pytest 63 | run: | 64 | pytest callflow/tests -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # callflow specific 3 | 4 | *.csv 5 | *.h5 6 | 7 | .callflow 8 | 9 | data/* 10 | app/node_modules* 11 | 12 | # symlinks for installation 13 | callflow/app 14 | callflow/data 15 | callflow/examples 16 | callflow/server 17 | 18 | designs/* 19 | videos/* 20 | 21 | # ------------------------------------------------------------------------------ 22 | # Editor hidden directories 23 | *.DS_Store 24 | .vscode 25 | *~ 26 | 27 | 28 | # Byte-compiled / optimized / DLL files 29 | __pycache__/ 30 | *.py[cod] 31 | *$py.class 32 | .cache 33 | .pytest_cache 34 | 35 | # Distribution / packaging 36 | .Python 37 | *.egg-info/ 38 | *.egg 39 | build/ 40 | dist/ 41 | docs/_build 42 | 43 | # Jupyter Notebook checkpoints 44 | .ipynb_checkpoints 45 | 46 | # Ignore Screenshots 47 | *.png 48 | 49 | # Pycharm IDE files 50 | .idea/* 51 | venv/* 52 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/psf/black 3 | rev: stable 4 | hooks: 5 | - id: black 6 | language_version: python3.8 7 | - repo: https://gitlab.com/pycqa/flake8 8 | rev: 3.7.9 9 | hooks: 10 | - id: flake8 -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.7" 4 | cache: pip 5 | 6 | branches: 7 | only: 8 | - develop 9 | - /^releases\/.*$/ 10 | 11 | install: 12 | - pip install --upgrade -r requirements.txt 13 | - git clone https://github.com/LLNL/Caliper.git 14 | - cd Caliper 15 | - mkdir build && cd build 16 | - cmake -DCMAKE_INSTALL_PREFIX=${VIRTUAL_ENV} ../ 17 | - make && make install 18 | - cd ../../ 19 | - rm -rf Caliper 20 | - python setup.py install 21 | - npm install --prefix=app 22 | - npm run lint --prefix=app 23 | 24 | jobs: 25 | fast_finish: true 26 | include: 27 | - stage: "tests" 28 | script: 29 | - echo -e "Running test (caliper-simple-json)" 30 | - callflow --process --ensemble_process --reset --data_path ./data/caliper-simple-json --profile_format caliper_json 31 | 32 | - echo -e "Running test (caliper-lulesh-json)" 33 | - callflow --process --ensemble_process --reset --data_path ./data/caliper-lulesh-json --profile_format caliper_json 34 | 35 | - echo -e "Running test (caliper-simple-cali)" 36 | - callflow --process --ensemble_process --reset --data_path ./data/caliper-simple-cali --profile_format caliper 37 | 38 | - echo -e "Running test (caliper-lulesh-cali)" 39 | - callflow --process --ensemble_process --reset --data_path ./data/caliper-lulesh-cali --profile_format caliper 40 | 41 | - echo -e "Running test (hpctoolkit-cpi-database)" 42 | - callflow --process --ensemble_process --reset --data_path ./data/hpctoolkit-cpi-database --profile_format hpctoolkit 43 | 44 | - echo -e "Running test (hpctoolkit-allgather-database)" 45 | - callflow --process --ensemble_process --reset --data_path ./data/hpctoolkit-allgather-database --profile_format hpctoolkit 46 | 47 | - stage: "style check" 48 | install: skip 49 | script: 50 | - pip install --upgrade black flake8 pylint 51 | - flake8 --exclude=examples 52 | - black --diff --check . 53 | - pylint --disable=all --enable=missing-docstring callflow 54 | 55 | notifications: 56 | email: 57 | recipients: 58 | - spkesavan@ucdavis.edu 59 | on_success: change 60 | on_failure: always 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include pyproject.toml 2 | 3 | # Include the README 4 | include *.md 5 | 6 | # Include the license file 7 | include LICENSE 8 | 9 | # Include the data files 10 | recursive-include data * 11 | recursive-include examples * 12 | recursive-include app/dist * 13 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This work was produced under the auspices of the U.S. Department of 2 | Energy by Lawrence Livermore National Laboratory under Contract 3 | DE-AC52-07NA27344. This work was also supported in part by the 4 | U.S. Department of Energy grant DE-SC0014917. 5 | 6 | This work was prepared as an account of work sponsored by an agency of 7 | the United States Government. Neither the United States Government nor 8 | Lawrence Livermore National Security, LLC, nor any of their employees 9 | makes any warranty, expressed or implied, or assumes any legal liability 10 | or responsibility for the accuracy, completeness, or usefulness of any 11 | information, apparatus, product, or process disclosed, or represents that 12 | its use would not infringe privately owned rights. 13 | 14 | Reference herein to any specific commercial product, process, or service 15 | by trade name, trademark, manufacturer, or otherwise does not necessarily 16 | constitute or imply its endorsement, recommendation, or favoring by the 17 | United States Government or Lawrence Livermore National Security, LLC. 18 | 19 | The views and opinions of authors expressed herein do not necessarily 20 | state or reflect those of the United States Government or Lawrence 21 | Livermore National Security, LLC, and shall not be used for advertising 22 | or product endorsement purposes. 23 | -------------------------------------------------------------------------------- /app/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | .gitignore 3 | build/** 4 | src/lib/backup/* 5 | src/lib/interactions/spin.js 6 | vue.config.js -------------------------------------------------------------------------------- /app/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:vue/essential" 9 | ], 10 | "globals": { 11 | "Atomics": "readonly", 12 | "SharedArrayBuffer": "readonly" 13 | }, 14 | "parserOptions": { 15 | "ecmaVersion": 2018, 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "vue" 20 | ], 21 | "overrides": [ 22 | { 23 | "files": ["node_modules/*", "src/thirdParty/*", "src/unused/*", "vue.config.js"], 24 | "rules": { 25 | "require-jsdoc": "off" 26 | } 27 | } 28 | ], 29 | "rules": { 30 | "indent": [ 31 | "error", 32 | "tab" 33 | ], 34 | "linebreak-style": [ 35 | "error", 36 | "unix" 37 | ], 38 | "quotes": [ 39 | "error", 40 | "double" 41 | ], 42 | "semi": [ 43 | "error", 44 | "always" 45 | ], 46 | "no-unused-vars": "off", 47 | "no-console": "off", 48 | "global-require": "off", 49 | "no-prototype-builtins": "off", 50 | } 51 | }; -------------------------------------------------------------------------------- /app/babel.config.js: -------------------------------------------------------------------------------- 1 | { 2 | { 3 | { 4 | "vue/dist/vue.js"; 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /app/dist/fonts/MaterialIcons-Regular.0509ab09.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/app/dist/fonts/MaterialIcons-Regular.0509ab09.woff2 -------------------------------------------------------------------------------- /app/dist/fonts/MaterialIcons-Regular.29b882f0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/app/dist/fonts/MaterialIcons-Regular.29b882f0.woff -------------------------------------------------------------------------------- /app/dist/fonts/MaterialIcons-Regular.96c47680.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/app/dist/fonts/MaterialIcons-Regular.96c47680.eot -------------------------------------------------------------------------------- /app/dist/fonts/MaterialIcons-Regular.da4ea5cd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/app/dist/fonts/MaterialIcons-Regular.da4ea5cd.ttf -------------------------------------------------------------------------------- /app/dist/index.html: -------------------------------------------------------------------------------- 1 | Vue App
-------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | CallFlow 16 | 17 | 18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CallFlow", 3 | "version": "1.3.0", 4 | "description": "Visualization tool for Calling Context Trees (CCTs)", 5 | "author": "Suraj Kesavan, Harsh Bhatia", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build && bash update_build.sh", 9 | "lint": "vue-cli-service lint" 10 | }, 11 | "dependencies": { 12 | "bootstrap": "^4.5.0", 13 | "bootstrap-vue": "^2.15.0", 14 | "chroma-js": "^2.0.4", 15 | "core-js": "^3.6.5", 16 | "d3": "^7.6.1", 17 | "d3-axis": "^1.0.12", 18 | "d3-context-menu": "^1.1.2", 19 | "d3-scale": "^3.2.3", 20 | "d3-selection-multi": "^1.0.1", 21 | "dagre-d3": "^0.6.3", 22 | "html-entities": "^1.3.1", 23 | "isarray": "^2.0.5", 24 | "lib": "file:src/lib", 25 | "material-design-icons-iconfont": "^5.0.1", 26 | "moment": "^2.29.4", 27 | "robust-point-in-polygon": "^1.0.3", 28 | "socket.io-client": "^2.3.1", 29 | "splitpanes": "^1.14.2", 30 | "vue": "^2.6.12", 31 | "vue-material": "^1.0.0-beta-14", 32 | "vue-router": "^3.4.6", 33 | "vue-socket.io": "^3.0.10", 34 | "vue-socket.io-extended": "^3.2.1", 35 | "vuetify": "^2.6.10", 36 | "vuex": "^3.5.1" 37 | }, 38 | "devDependencies": { 39 | "@babel/core": "^7.0.0-0", 40 | "@vue/cli-plugin-babel": "^5.0.8", 41 | "@vue/cli-plugin-eslint": "^5.0.8", 42 | "@vue/cli-service": "^5.0.8", 43 | "babel-eslint": "^10.1.0", 44 | "eslint": "^8.24.0", 45 | "eslint-plugin-vue": "^7.0.0-alpha.8", 46 | "sass": "^1.32.0", 47 | "sass-loader": "^10.0.0", 48 | "vue-cli-plugin-vuetify": "~2.1.0", 49 | "vue-template-compiler": "^2.6.11", 50 | "vuetify-loader": "^1.7.0" 51 | }, 52 | "eslintConfig": { 53 | "root": true, 54 | "env": { 55 | "node": true 56 | }, 57 | "extends": [ 58 | "plugin:vue/essential", 59 | "eslint:recommended" 60 | ], 61 | "parserOptions": { 62 | "parser": "babel-eslint" 63 | }, 64 | "rules": {} 65 | }, 66 | "postcss": {}, 67 | "browserslist": [ 68 | "> 1%", 69 | "last 2 versions", 70 | "not ie <= 8" 71 | ], 72 | "engines": { 73 | "node": ">= 13.7.0", 74 | "npm": ">= 6.9.0" 75 | }, 76 | "license": "MIT", 77 | "pre-commit": [ 78 | "lint" 79 | ], 80 | "repository": { 81 | "type": "git", 82 | "url": "git://github.com/LLNL/CallFlow.git" 83 | }, 84 | "resolutions": { 85 | "babel-core": "7.0.0-bridge.0" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/components/App.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 30 | 31 | 81 | 82 | -------------------------------------------------------------------------------- /app/src/components/Summary.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/components/SuperGraph.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/components/boxplot/box.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/boxplot/statistics.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/components/boxplot/tooltip.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/callsiteCorrespondence/boxplot.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/components/callsiteInformation/boxplot.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/components/ensembleHistogram/tooltip.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/ensembleScatterplot/tooltip.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/general/footer.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 15 | 16 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/components/general/infoChip.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 31 | 32 | 45 | -------------------------------------------------------------------------------- /app/src/components/general/loader.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/components/general/runSelection.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 113 | -------------------------------------------------------------------------------- /app/src/components/general/settings/header.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/components/general/settings/select.vue: -------------------------------------------------------------------------------- 1 | :wq 18 | 19 | -------------------------------------------------------------------------------- /app/src/components/general/splitControl.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/components/general/toolbar.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/components/general/viewSelection.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/components/moduleHierarchy/lib/comparator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | export default class Comparator { 9 | /** 10 | * @param {function(a: *, b: *)} [compareFunction] - It may be custom compare function that, let's 11 | * say may compare custom objects together. 12 | */ 13 | constructor(compareFunction) { 14 | this.compare = compareFunction || Comparator.defaultCompareFunction; 15 | } 16 | 17 | /** 18 | * Default comparison function. It just assumes that "a" and "b" are strings or numbers. 19 | * @param {(string|number)} a 20 | * @param {(string|number)} b 21 | * @returns {number} 22 | */ 23 | static defaultCompareFunction(a, b) { 24 | if (a === b) { 25 | return 0; 26 | } 27 | 28 | return a < b ? -1 : 1; 29 | } 30 | 31 | /** 32 | * Checks if two variables are equal. 33 | * @param {*} a 34 | * @param {*} b 35 | * @return {boolean} 36 | */ 37 | equal(a, b) { 38 | return this.compare(a, b) === 0; 39 | } 40 | 41 | /** 42 | * Checks if variable "a" is less than "b". 43 | * @param {*} a 44 | * @param {*} b 45 | * @return {boolean} 46 | */ 47 | lessThan(a, b) { 48 | return this.compare(a, b) < 0; 49 | } 50 | 51 | /** 52 | * Checks if variable "a" is greater than "b". 53 | * @param {*} a 54 | * @param {*} b 55 | * @return {boolean} 56 | */ 57 | greaterThan(a, b) { 58 | return this.compare(a, b) > 0; 59 | } 60 | 61 | /** 62 | * Checks if variable "a" is less than or equal to "b". 63 | * @param {*} a 64 | * @param {*} b 65 | * @return {boolean} 66 | */ 67 | lessThanOrEqual(a, b) { 68 | return this.lessThan(a, b) || this.equal(a, b); 69 | } 70 | 71 | /** 72 | * Checks if variable "a" is greater than or equal to "b". 73 | * @param {*} a 74 | * @param {*} b 75 | * @return {boolean} 76 | */ 77 | greaterThanOrEqual(a, b) { 78 | return this.greaterThan(a, b) || this.equal(a, b); 79 | } 80 | 81 | /** 82 | * Reverses the comparison order. 83 | */ 84 | reverse() { 85 | const compareOriginal = this.compare; 86 | this.compare = (a, b) => compareOriginal(b, a); 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/components/moduleHierarchy/lib/edge.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | export default class GraphEdge { 9 | /** 10 | * @param {GraphVertex} startVertex 11 | * @param {GraphVertex} endVertex 12 | * @param {number} [weight=1] 13 | */ 14 | constructor(startVertex, endVertex, weight = 0) { 15 | this.startVertex = startVertex; 16 | this.endVertex = endVertex; 17 | this.weight = weight; 18 | } 19 | 20 | /** 21 | * @return {string} 22 | */ 23 | getKey() { 24 | const startVertexKey = this.startVertex.getKey(); 25 | const endVertexKey = this.endVertex.getKey(); 26 | 27 | return `${startVertexKey}_${endVertexKey}`; 28 | } 29 | 30 | /** 31 | * @return {GraphEdge} 32 | */ 33 | reverse() { 34 | const tmp = this.startVertex; 35 | this.startVertex = this.endVertex; 36 | this.endVertex = tmp; 37 | 38 | return this; 39 | } 40 | 41 | /** 42 | * @return {string} 43 | */ 44 | toString() { 45 | return this.getKey(); 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/components/moduleHierarchy/lib/linkedListNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | export default class LinkedListNode { 9 | constructor(value, next = null) { 10 | this.value = value; 11 | this.next = next; 12 | } 13 | 14 | toString(callback) { 15 | return callback ? callback(this.value) : `${this.value}`; 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/components/moduleHierarchy/lib/node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import LinkedList from "./linkedList"; 9 | 10 | export default class GraphVertex { 11 | /** 12 | * @param {*} value 13 | */ 14 | constructor(value) { 15 | if (value === undefined) { 16 | throw new Error("Graph vertex must have a value"); 17 | } 18 | 19 | /** 20 | * @param {GraphEdge} edgeA 21 | * @param {GraphEdge} edgeB 22 | */ 23 | const edgeComparator = (edgeA, edgeB) => { 24 | if (edgeA.getKey() === edgeB.getKey()) { 25 | return 0; 26 | } 27 | 28 | return edgeA.getKey() < edgeB.getKey() ? -1 : 1; 29 | }; 30 | 31 | // Normally you would store string value like vertex name. 32 | // But generally it may be any object as well 33 | this.value = value; 34 | this.edges = new LinkedList(edgeComparator); 35 | } 36 | 37 | /** 38 | * @param {GraphEdge} edge 39 | * @returns {GraphVertex} 40 | */ 41 | addEdge(edge) { 42 | this.edges.append(edge); 43 | 44 | return this; 45 | } 46 | 47 | /** 48 | * @param {GraphEdge} edge 49 | */ 50 | deleteEdge(edge) { 51 | this.edges.delete(edge); 52 | } 53 | 54 | /** 55 | * @returns {GraphVertex[]} 56 | */ 57 | getNeighbors() { 58 | const edges = this.edges.toArray(); 59 | 60 | /** @param {LinkedListNode} node */ 61 | const neighborsConverter = (node) => { 62 | return node.value.startVertex === this ? node.value.endVertex : node.value.startVertex; 63 | }; 64 | 65 | // Return either start or end vertex. 66 | // For undirected graphs it is possible that current vertex will be the end one. 67 | return edges.map(neighborsConverter); 68 | } 69 | 70 | /** 71 | * @return {GraphEdge[]} 72 | */ 73 | getEdges() { 74 | return this.edges.toArray().map(linkedListNode => linkedListNode.value); 75 | } 76 | 77 | /** 78 | * @return {number} 79 | */ 80 | getDegree() { 81 | return this.edges.toArray().length; 82 | } 83 | 84 | /** 85 | * @param {GraphEdge} requiredEdge 86 | * @returns {boolean} 87 | */ 88 | hasEdge(requiredEdge) { 89 | const edgeNode = this.edges.find({ 90 | callback: edge => edge === requiredEdge, 91 | }); 92 | 93 | return !!edgeNode; 94 | } 95 | 96 | /** 97 | * @param {GraphVertex} vertex 98 | * @returns {boolean} 99 | */ 100 | hasNeighbor(vertex) { 101 | const vertexNode = this.edges.find({ 102 | callback: edge => edge.startVertex === vertex || edge.endVertex === vertex, 103 | }); 104 | 105 | return !!vertexNode; 106 | } 107 | 108 | /** 109 | * @param {GraphVertex} vertex 110 | * @returns {(GraphEdge|null)} 111 | */ 112 | findEdge(vertex) { 113 | const edgeFinder = (edge) => { 114 | return edge.startVertex === vertex || edge.endVertex === vertex; 115 | }; 116 | 117 | const edge = this.edges.find({ callback: edgeFinder }); 118 | 119 | return edge ? edge.value : null; 120 | } 121 | 122 | /** 123 | * @returns {string} 124 | */ 125 | getKey() { 126 | return this.value; 127 | } 128 | 129 | /** 130 | * @return {GraphVertex} 131 | */ 132 | deleteAllEdges() { 133 | this.getEdges().forEach(edge => this.deleteEdge(edge)); 134 | 135 | return this; 136 | } 137 | 138 | /** 139 | * @param {function} [callback] 140 | * @returns {string} 141 | */ 142 | toString(callback) { 143 | return callback ? callback(this.value) : `${this.value}`; 144 | } 145 | } -------------------------------------------------------------------------------- /app/src/components/moduleHierarchy/lib/queue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import LinkedList from "./linkedList"; 9 | 10 | export default class Queue { 11 | constructor() { 12 | // We're going to implement Queue based on LinkedList since the two 13 | // structures are quite similar. Namely, they both operate mostly on 14 | // the elements at the beginning and the end. Compare enqueue/dequeue 15 | // operations of Queue with append/deleteHead operations of LinkedList. 16 | this.linkedList = new LinkedList(); 17 | } 18 | 19 | /** 20 | * @return {boolean} 21 | */ 22 | isEmpty() { 23 | return !this.linkedList.head; 24 | } 25 | 26 | /** 27 | * Read the element at the front of the queue without removing it. 28 | * @return {*} 29 | */ 30 | peek() { 31 | if (!this.linkedList.head) { 32 | return null; 33 | } 34 | 35 | return this.linkedList.head.value; 36 | } 37 | 38 | /** 39 | * Add a new element to the end of the queue (the tail of the linked list). 40 | * This element will be processed after all elements ahead of it. 41 | * @param {*} value 42 | */ 43 | enqueue(value) { 44 | this.linkedList.append(value); 45 | } 46 | 47 | /** 48 | * Remove the element at the front of the queue (the head of the linked list). 49 | * If the queue is empty, return null. 50 | * @return {*} 51 | */ 52 | dequeue() { 53 | const removedHead = this.linkedList.deleteHead(); 54 | return removedHead ? removedHead.value : null; 55 | } 56 | 57 | /** 58 | * @param [callback] 59 | * @return {string} 60 | */ 61 | toString(callback) { 62 | // Return string representation of the queue's linked list. 63 | return this.linkedList.toString(callback); 64 | } 65 | } -------------------------------------------------------------------------------- /app/src/components/moduleHierarchy/tooltip.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/nodeLink/d3-inputbox.js: -------------------------------------------------------------------------------- 1 | import * as d3 from "d3"; 2 | 3 | export default function d3InputBox() { 4 | const radius = 3; 5 | 6 | function render(selection) { 7 | selection.each(function (d, i) { 8 | const g = d3.select(this) 9 | .attr("id", "d3-inputbox" + i) 10 | .attr("transform", "translate(" + d.x + "," + d.y + ")"); 11 | 12 | g.append("text") 13 | .attr("dx", 12) 14 | .attr("dy", d.height / 2 + 4) 15 | .text(d.label); 16 | 17 | g.append("text") 18 | .attr("id", "value") 19 | .attr("dx", d.width - 12) 20 | .attr("dy", d.height / 2 + 4) 21 | .text(d.supernode) 22 | .classed("value", true); 23 | 24 | g.insert("rect", "text", "value") 25 | .attr("x", 0) 26 | .attr("y", 0) 27 | .attr("width", d.width) 28 | .attr("height", d.height) 29 | .attr("rx", radius) 30 | .attr("ry", radius) 31 | .on("mouseover", mouseover) 32 | .on("mouseout", mouseout) 33 | .on("click", click); 34 | }); 35 | 36 | } 37 | 38 | function mouseover() { 39 | d3.select(this.parentNode).select("rect").classed("active", true); 40 | } 41 | 42 | function mouseout() { 43 | d3.select(this.parentNode).select("rect").classed("active", false); 44 | } 45 | 46 | function click(d, i) { 47 | d3.selectAll("foreignObject").remove(); 48 | 49 | const p = this.parentNode; 50 | const field = d3.select(p); 51 | 52 | var xy0 = this.getBBox(); 53 | var xy1 = p.getBBox(); 54 | 55 | xy0.x -= xy1.x - d.width + 96; 56 | xy0.y -= xy1.y + 2 - 8; 57 | 58 | const frm = field.append("foreignObject"); 59 | const inp = frm 60 | .attr("x", xy0.x) 61 | .attr("y", xy0.y) 62 | .attr("width", 80) 63 | .attr("height", 32) 64 | .append("xhtml:form") 65 | .append("input") 66 | .style("width", "80px") 67 | .style("height", "20") 68 | .attr("type", "selection") 69 | .on("change", function () { 70 | d.supernode = this.supernode; 71 | field.select("#value").text(d.supernode); 72 | }) 73 | .attr("value", function () { return d.supernode; }) 74 | .on("keypress", function () { 75 | var e = d3.event; 76 | 77 | if (e.keyCode == 13) { 78 | 79 | d.supernode = inp.node().value; 80 | field.select("foreignObject").remove(); 81 | field.select("#value").text(d.supernode); 82 | 83 | } 84 | }); 85 | } 86 | 87 | return render; 88 | } -------------------------------------------------------------------------------- /app/src/components/nodeLink/tooltip.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/components/sankey/encodings/mean.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/sankey/encodings/meanDiff.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/sankey/encodings/meanGradients.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/sankey/encodings/targetLine.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/sankey/lib/bfs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import Queue from "../../../data-structures/queue/Queue"; 9 | /** 10 | * @typedef {Object} Callbacks 11 | * 12 | * @property {function(vertices: Object): boolean} [allowTraversal] - 13 | * Determines whether DFS should traverse from the vertex to its neighbor 14 | * (along the edge). By default prohibits visiting the same vertex again. 15 | * 16 | * @property {function(vertices: Object)} [enterVertex] - Called when BFS enters the vertex. 17 | * 18 | * @property {function(vertices: Object)} [leaveVertex] - Called when BFS leaves the vertex. 19 | */ 20 | 21 | /** 22 | * @param {Callbacks} [callbacks] 23 | * @returns {Callbacks} 24 | */ 25 | function initCallbacks(callbacks = {}) { 26 | const initiatedCallback = callbacks; 27 | 28 | const stubCallback = () => { }; 29 | 30 | const allowTraversalCallback = ( 31 | () => { 32 | const seen = {}; 33 | return ({ nextVertex }) => { 34 | if (!seen[nextVertex.getKey()]) { 35 | seen[nextVertex.getKey()] = true; 36 | return true; 37 | } 38 | return false; 39 | }; 40 | } 41 | )(); 42 | 43 | initiatedCallback.allowTraversal = callbacks.allowTraversal || allowTraversalCallback; 44 | initiatedCallback.enterVertex = callbacks.enterVertex || stubCallback; 45 | initiatedCallback.leaveVertex = callbacks.leaveVertex || stubCallback; 46 | 47 | return initiatedCallback; 48 | } 49 | 50 | /** 51 | * @param {Graph} graph 52 | * @param {GraphVertex} startVertex 53 | * @param {Callbacks} [originalCallbacks] 54 | */ 55 | export default function bfs (graph, startVertex, originalCallbacks) { 56 | const callbacks = initCallbacks(originalCallbacks); 57 | const vertexQueue = new Queue(); 58 | 59 | // Do initial queue setup. 60 | vertexQueue.enqueue(startVertex); 61 | 62 | let previousVertex = null; 63 | 64 | // Traverse all vertices from the queue. 65 | while (!vertexQueue.isEmpty()) { 66 | const currentVertex = vertexQueue.dequeue(); 67 | callbacks.enterVertex({ currentVertex, previousVertex }); 68 | 69 | // Add all neighbors to the queue for future traversals. 70 | graph.getNeighbors(currentVertex).forEach((nextVertex) => { 71 | if (callbacks.allowTraversal({ previousVertex, currentVertex, nextVertex })) { 72 | vertexQueue.enqueue(nextVertex); 73 | } 74 | }); 75 | 76 | callbacks.leaveVertex({ currentVertex, previousVertex }); 77 | 78 | // Memorize current vertex before next loop. 79 | previousVertex = currentVertex; 80 | } 81 | } -------------------------------------------------------------------------------- /app/src/components/sankey/lib/detectcycle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import depthFirstSearch from "./dfs"; 9 | 10 | /** 11 | * Detect cycle in directed graph using Depth First Search. 12 | * 13 | * @param {Graph} graph 14 | */ 15 | export default function detectDirectedCycle(graph) { 16 | let cycle = null; 17 | 18 | // Will store parents (previous vertices) for all visited nodes. 19 | // This will be needed in order to specify what path exactly is a cycle. 20 | const dfsParentMap = {}; 21 | 22 | // White set (UNVISITED) contains all the vertices that haven't been visited at all. 23 | const whiteSet = {}; 24 | 25 | // Gray set (VISITING) contains all the vertices that are being visited right now 26 | // (in current path). 27 | const graySet = {}; 28 | 29 | // Black set (VISITED) contains all the vertices that has been fully visited. 30 | // Meaning that all children of the vertex has been visited. 31 | const blackSet = {}; 32 | 33 | // If we encounter vertex in gray set it means that we've found a cycle. 34 | // Because when vertex in gray set it means that its neighbors or its neighbors 35 | // neighbors are still being explored. 36 | 37 | // Init white set and add all vertices to it. 38 | /** @param {GraphVertex} vertex */ 39 | graph.getAllVertices().forEach((vertex) => { 40 | whiteSet[vertex.getKey()] = vertex; 41 | }); 42 | 43 | // Describe BFS callbacks. 44 | const callbacks = { 45 | enterVertex: ({ currentVertex, previousVertex }) => { 46 | if (graySet[currentVertex.getKey()]) { 47 | // If current vertex already in grey set it means that cycle is detected. 48 | // Let's detect cycle path. 49 | cycle = {}; 50 | 51 | let currentCycleVertex = currentVertex; 52 | let previousCycleVertex = previousVertex; 53 | 54 | while (previousCycleVertex.getKey() !== currentVertex.getKey()) { 55 | cycle[currentCycleVertex.getKey()] = previousCycleVertex; 56 | currentCycleVertex = previousCycleVertex; 57 | previousCycleVertex = dfsParentMap[previousCycleVertex.getKey()]; 58 | } 59 | 60 | cycle[currentCycleVertex.getKey()] = previousCycleVertex; 61 | } else { 62 | // Otherwise let's add current vertex to gray set and remove it from white set. 63 | graySet[currentVertex.getKey()] = currentVertex; 64 | delete whiteSet[currentVertex.getKey()]; 65 | 66 | // Update DFS parents list. 67 | dfsParentMap[currentVertex.getKey()] = previousVertex; 68 | } 69 | }, 70 | leaveVertex: ({ currentVertex }) => { 71 | // If all node's children has been visited let's remove it from gray set 72 | // and move it to the black set meaning that all its neighbors are visited. 73 | blackSet[currentVertex.getKey()] = currentVertex; 74 | delete graySet[currentVertex.getKey()]; 75 | }, 76 | allowTraversal: ({ nextVertex }) => { 77 | // If cycle was detected we must forbid all further traversing since it will 78 | // cause infinite traversal loop. 79 | if (cycle) { 80 | return false; 81 | } 82 | 83 | // Allow traversal only for the vertices that are not in black set 84 | // since all black set vertices have been already visited. 85 | return !blackSet[nextVertex.getKey()]; 86 | }, 87 | }; 88 | 89 | // Start exploring vertices. 90 | while (Object.keys(whiteSet).length) { 91 | // Pick fist vertex to start BFS from. 92 | const firstWhiteKey = Object.keys(whiteSet)[0]; 93 | const startVertex = whiteSet[firstWhiteKey]; 94 | 95 | console.debug(firstWhiteKey, startVertex); 96 | // Do Depth First Search. 97 | depthFirstSearch(graph, startVertex, callbacks); 98 | } 99 | 100 | return [cycle, graySet, blackSet, whiteSet]; 101 | } -------------------------------------------------------------------------------- /app/src/components/sankey/lib/dfs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | /** 9 | * @typedef {Object} Callbacks 10 | * 11 | * @property {function(vertices: Object): boolean} [allowTraversal] - 12 | * Determines whether DFS should traverse from the vertex to its neighbor 13 | * (along the edge). By default prohibits visiting the same vertex again. 14 | * 15 | * @property {function(vertices: Object)} [enterVertex] - Called when DFS enters the vertex. 16 | * 17 | * @property {function(vertices: Object)} [leaveVertex] - Called when DFS leaves the vertex. 18 | */ 19 | 20 | /** 21 | * @param {Callbacks} [callbacks] 22 | * @returns {Callbacks} 23 | */ 24 | function initCallbacks(callbacks = {}) { 25 | const initiatedCallback = callbacks; 26 | 27 | const stubCallback = () => { }; 28 | 29 | const allowTraversalCallback = ( 30 | () => { 31 | const seen = {}; 32 | return ({ nextVertex }) => { 33 | if (!seen[nextVertex.getKey()]) { 34 | seen[nextVertex.getKey()] = true; 35 | return true; 36 | } 37 | return false; 38 | }; 39 | } 40 | )(); 41 | 42 | initiatedCallback.allowTraversal = callbacks.allowTraversal || allowTraversalCallback; 43 | initiatedCallback.enterVertex = callbacks.enterVertex || stubCallback; 44 | initiatedCallback.leaveVertex = callbacks.leaveVertex || stubCallback; 45 | 46 | return initiatedCallback; 47 | } 48 | 49 | /** 50 | * @param {Graph} graph 51 | * @param {GraphVertex} currentVertex 52 | * @param {GraphVertex} previousVertex 53 | * @param {Callbacks} callbacks 54 | */ 55 | function depthFirstSearchRecursive(graph, currentVertex, previousVertex, callbacks) { 56 | callbacks.enterVertex({ currentVertex, previousVertex }); 57 | 58 | graph.getNeighbors(currentVertex).forEach((nextVertex) => { 59 | if (callbacks.allowTraversal({ previousVertex, currentVertex, nextVertex })) { 60 | depthFirstSearchRecursive(graph, nextVertex, currentVertex, callbacks); 61 | } 62 | }); 63 | 64 | callbacks.leaveVertex({ currentVertex, previousVertex }); 65 | } 66 | /** 67 | * @param {Graph} graph 68 | * @param {GraphVertex} startVertex 69 | * @param {Callbacks} [callbacks] 70 | */ 71 | export default function depthFirstSearch(graph, startVertex, callbacks) { 72 | const previousVertex = null; 73 | depthFirstSearchRecursive(graph, startVertex, previousVertex, initCallbacks(callbacks)); 74 | } -------------------------------------------------------------------------------- /app/src/components/sankey/miniHistograms.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/singleHistogram/tooltip.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/components/summary/config.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 51 | 52 | 53 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/components/summary/moduleMap.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/components/summary/profile.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 36 | 37 | 69 | 70 | -------------------------------------------------------------------------------- /app/src/lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lib", 3 | "version": "0.0.1", 4 | "description": "Use package.json to make lib a module to avoid relative path", 5 | "readme": "https://www.freecodecamp.org/news/how-to-structure-your-project-and-manage-static-resources-in-react-native-6f4cfc947d92/#use-package-json-to-avoid-relative-path" 6 | } -------------------------------------------------------------------------------- /app/src/lib/routing/APIService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | class APIService { 9 | /** 10 | * API service for CallFlow. 11 | * Two kinds of requests are supported, GET and POST. 12 | * fetch API is being used to trigger the requests. 13 | */ 14 | constructor() { 15 | this.url = "http://localhost:5000/"; // For local 16 | } 17 | 18 | /** 19 | * Force to reject the promise in the specified seconds. 20 | * @param {Numeric} ms milliseconds before rejecting the promise 21 | * @param {Promise} promise Promise of interest. 22 | * @return {Promise} A promise with timeout. 23 | */ 24 | timeoutPromise(ms, promise) { 25 | return new Promise((resolve, reject) => { 26 | const timeoutId = setTimeout(() => { 27 | reject(new Error("Promise times out")); 28 | }, ms); 29 | promise.then( 30 | (res) => { 31 | clearTimeout(timeoutId); 32 | resolve(res); 33 | }, 34 | (err) => { 35 | clearTimeout(timeoutId); 36 | reject(err); 37 | }, 38 | ); 39 | }); 40 | } 41 | 42 | /** 43 | * Send a POST request to the server. 44 | * @param {String} endpoint 45 | * @param {JSON} jsonBody 46 | * @return {Promise} response 47 | */ 48 | POSTRequest(endpoint="", jsonBody={}) { 49 | const fullURL = this.url + endpoint; 50 | console.log("[POST Request]", fullURL, "body: ", jsonBody); 51 | const httpResponse = fetch(fullURL, { 52 | method: "POST", 53 | cache: "default", // *default, no-cache, reload, force-cache, only-if-cached 54 | headers: {"Content-Type": "application/json"}, 55 | body: JSON.stringify(jsonBody), 56 | }).then((response) => { 57 | switch (response.status) { 58 | case 200: 59 | return response.json(); 60 | case 401: 61 | return Promise.reject("unauthorized"); 62 | case 500: 63 | return Promise.reject("not_allowed"); 64 | default: 65 | return Promise.reject("unknown_error"); 66 | } 67 | }).catch((error) => { 68 | console.error(error); 69 | return Promise.reject(error); 70 | }); 71 | return this.timeoutPromise(10000, httpResponse); 72 | } 73 | 74 | /** 75 | * Send a GET request to the server. 76 | * @param {String} endpoint 77 | * @param {String} requestType 78 | * @param {JSON} headers 79 | * @return {Promise} response 80 | */ 81 | GETRequest(endpoint="", headers={"Content-Type": "application/json"}) { 82 | const fullURL = this.url + endpoint; 83 | console.debug("[GET Request]", fullURL, headers); 84 | const httpResponse = fetch(fullURL, { 85 | method: "GET", 86 | headers: headers, 87 | cache: "default", // *default, no-cache, reload, force-cache, only-if-cached 88 | }).then((response) => { 89 | switch (response.status) { 90 | case 200: 91 | return response.json(); 92 | case 401: 93 | return Promise.reject("unauthorized"); 94 | case 500: 95 | return Promise.reject("not_allowed"); 96 | default: 97 | return Promise.reject("unknown_error"); 98 | } 99 | }).catch((error) => { 100 | console.error(error); 101 | return Promise.reject(error); 102 | }); 103 | return this.timeoutPromise(10000, httpResponse); 104 | } 105 | } 106 | export default new APIService(); 107 | -------------------------------------------------------------------------------- /app/src/lib/routing/EventHandler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import Vue from "vue"; 9 | 10 | const EventBus = new Vue(); 11 | 12 | export default EventBus; -------------------------------------------------------------------------------- /app/src/lib/views/hist_view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import * as d3 from "d3"; 9 | import { pallette, percentColToD3Rgb } from "./colors.js"; 10 | 11 | const genX = (data, svgArea, domain) => { 12 | if (domain === undefined) { 13 | domain = d3.extent(data); 14 | } 15 | return d3.scaleLinear() 16 | .domain(domain).nice() 17 | .range([0, svgArea.width]); 18 | }; 19 | 20 | const genY = (data, svgArea, domain) => { 21 | if (domain === undefined) { 22 | domain = d3.extent(data); 23 | } 24 | return d3.scaleLinear() 25 | .domain(domain).nice() 26 | .range([svgArea.height, 0]); 27 | }; 28 | 29 | const genXAxis = (x, svgArea) => { 30 | return g => g 31 | .attr("transform", `translate(0,${svgArea.height + 3})`) 32 | .attr("class", "xaxis") 33 | .call(d3.axisBottom(x).ticks(5).tickSize(3).tickSizeOuter(0)); 34 | }; 35 | 36 | const genYAxis = (y, svgArea) => { 37 | return g => g 38 | .attr("class", "yaxis") 39 | .call(d3.axisLeft(y).ticks(5).tickSize(2)); 40 | }; 41 | 42 | export const chart = (svgData, embType, offsetX, offsetY, w, h) => { 43 | svgData.svg.selectAll("*").remove(); 44 | d3.select(`#${svgData.dom_id}`) 45 | .style("opacity", 1) 46 | .style("top", offsetY + "px") 47 | .style("left", offsetX + "px") 48 | .style("width", w + "px") 49 | .style("height", h + "px"); 50 | 51 | const svgArea = svgData.svg_area; 52 | const svg = svgData.svg.attr("viewBox", [0, 0, svgArea.width, svgArea.height]); 53 | 54 | svg.append("path") 55 | .datum([{ 56 | x: -svgArea.margin.left, 57 | y: svgArea.height + svgArea.margin.bottom 58 | }, { 59 | x: -10, 60 | y: svgArea.height + 10 61 | }]) 62 | .attr("fill", "none") 63 | .attr("stroke", "#555555") 64 | .attr("stroke-opacity", 0.95) 65 | .attr("stroke-width", 0.5) 66 | .attr("d", d3.line() 67 | .x(d => d.x) 68 | .y(d => d.y)); 69 | svg.append("rect") 70 | .attr("x", -33) 71 | .attr("y", -svgArea.margin.top + 1) 72 | .attr("width", svgArea.width + svgArea.margin.right + 33 - 1) 73 | .attr("height", svgArea.height + svgArea.margin.top + 30 - 1) 74 | .style("fill", "#ffffff") 75 | .style("stroke", "#555555") 76 | .attr("stroke-opacity", 0.95) 77 | .attr("stroke-width", 0.5); 78 | 79 | const x = genX(undefined, svgArea, [svgData.data[0].val_min, svgData.data[0].val_max]); 80 | const xAxis = genXAxis(x, svgArea); 81 | const y = genY(undefined, svgArea, [0, svgData.data[0].freq_max]); 82 | const yAxis = genYAxis(y, svgArea); 83 | const unitW = svgArea.width / svgData.data[0].n_bins; 84 | 85 | svg.append("g") 86 | .call(xAxis); 87 | svg.append("g") 88 | .call(yAxis); 89 | 90 | let xLabel = ""; 91 | if (embType === "Y_n_dt" || embType === "Y_t_dn") { 92 | xLabel = "variable PC value"; 93 | } else if (embType === "Y_d_nt" || embType === "Y_t_nd") { 94 | xLabel = "instance PC value"; 95 | } else if (embType === "Y_n_td" || embType === "Y_d_tn") { 96 | xLabel = "time step PC value"; 97 | } 98 | 99 | svg.append("text") 100 | .attr("x", svgArea.width / 2) 101 | .attr("y", svgArea.height) 102 | .attr("dy", "2.5em") 103 | .style("text-anchor", "middle") 104 | .text(xLabel); 105 | svg.append("text") 106 | .attr("transform", "rotate(-90)") 107 | .attr("x", -svgArea.height / 2) 108 | .attr("dy", "-2.1em") 109 | .style("text-anchor", "middle") 110 | .text("relative frequency"); 111 | 112 | for (const [groupIdx, datum] of svgData.data.entries()) { 113 | svg.append("g") 114 | .selectAll("rect") 115 | .data(datum.rel_freqs) 116 | .enter().append("rect") 117 | .attr("class", "xSelectionArea") 118 | .attr("x", (d, i) => i * unitW) 119 | .attr("y", d => y(d)) 120 | .attr("width", unitW) 121 | .attr("height", d => svgArea.height - y(d)) 122 | .style("fill", percentColToD3Rgb(datum.color)) 123 | .style("opacity", 0.5); 124 | } 125 | 126 | return svg.node(); 127 | }; -------------------------------------------------------------------------------- /app/src/lib/views/matrixLayout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import * as d3 from "d3"; 9 | 10 | export default function adjacencyMatrixLayout() { 11 | var directed = true; 12 | var size = [1, 1]; 13 | var nodes = []; 14 | var edges = []; 15 | var adj = []; 16 | var useadj = false; 17 | var edgeWeight = function edgeWeight(d) { 18 | return 1; 19 | }; 20 | var nodeID = function nodeID(d) { 21 | return d.id; 22 | }; 23 | 24 | function matrix() { 25 | var width = size[0]; 26 | var height = size[1]; 27 | 28 | // const constructedMatrix = []; 29 | var matrix = []; 30 | var edgeHash = {}; 31 | let nodeWidth = width / adj.length; 32 | let nodeHeight = height / adj.length; 33 | var xScale = d3.scaleLinear().domain([0, adj.length]).range([0, width]); 34 | var yScale = d3.scaleLinear().domain([0, adj.length]).range([0, height]); 35 | 36 | for (let i = 0; i < adj.length; i += 1) { 37 | for (let j = 0; j < adj[i].length; j += 1) { 38 | var grid = { 39 | id: adj[i][j].id_x + "-" + adj[i][j].id_y, 40 | source: i, 41 | target: j, 42 | xid: adj[i][j].id_x, 43 | yid: adj[i][j].id_y, 44 | x: xScale(i), 45 | y: yScale(j), 46 | yAggr: yScale(j), 47 | weight: adj[i][j].z, 48 | height: nodeHeight, 49 | width: nodeWidth, 50 | }; 51 | matrix.push(grid); 52 | } 53 | } 54 | return matrix; 55 | } 56 | 57 | matrix.directed = function (x) { 58 | if (!arguments.length) { return directed; } 59 | directed = x; 60 | return matrix; 61 | }; 62 | 63 | matrix.size = function (x) { 64 | if (!arguments.length) { return size; } 65 | size = x; 66 | return matrix; 67 | }; 68 | 69 | matrix.nodes = function (x) { 70 | if (!arguments.length) { return nodes; } 71 | nodes = x; 72 | return matrix; 73 | }; 74 | 75 | matrix.links = function (x) { 76 | if (!arguments.length) { return edges; } 77 | edges = x; 78 | return matrix; 79 | }; 80 | 81 | matrix.adj = function (x) { 82 | if (!arguments.length) { return adj; } 83 | adj = x; 84 | return matrix; 85 | }; 86 | 87 | matrix.useadj = function (x) { 88 | if (!arguments.length) { return useadj; } 89 | useadj = true; 90 | return matrix; 91 | }; 92 | 93 | matrix.edgeWeight = function (x) { 94 | if (!arguments.length) { return edgeWeight; } 95 | if (typeof x === "function") { 96 | edgeWeight = x; 97 | } else { 98 | edgeWeight = function edgeWeight() { 99 | return x; 100 | }; 101 | } 102 | return matrix; 103 | }; 104 | 105 | matrix.nodeID = function (x) { 106 | if (!arguments.length) { return nodeID; } 107 | if (typeof x === "function") { 108 | nodeID = x; 109 | } 110 | return matrix; 111 | }; 112 | 113 | matrix.xAxis = function (calledG) { 114 | var nameScale = d3.scalePoint().domain(nodes.map(nodeID)).range([0, size[0]]).padding(1); 115 | 116 | var xAxis = d3.axisTop().scale(nameScale).tickSize(4); 117 | 118 | calledG.append("g").attr("class", "am-xAxis am-axis").call(xAxis).selectAll("text").style("text-anchor", "end").attr("transform", "translate(-10,-10) rotate(90)"); 119 | }; 120 | 121 | matrix.yAxis = function (calledG) { 122 | var nameScale = d3.scalePoint().domain(nodes.map(nodeID)).range([0, size[1]]).padding(1); 123 | 124 | var yAxis = d3.axisLeft().scale(nameScale).tickSize(4); 125 | 126 | calledG.append("g").attr("class", "am-yAxis am-axis").call(yAxis); 127 | }; 128 | 129 | return matrix; 130 | } 131 | -------------------------------------------------------------------------------- /app/src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 3 | * CallFlow Project Developers. See the top-level LICENSE file for details. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | */ 7 | 8 | import Vue from "vue"; 9 | import Router from "vue-router"; 10 | import BootstrapVue from "bootstrap-vue"; 11 | import VueMaterial from "vue-material"; 12 | import "vue-material/dist/vue-material.min.css"; 13 | import "vue-material/dist/theme/default.css"; 14 | import "vuetify/dist/vuetify.min.css"; 15 | import "material-design-icons-iconfont/dist/material-design-icons.css"; 16 | 17 | import App from "./components/App"; 18 | import Summary from "./components/Summary"; 19 | import CCT from "./components/CCT"; 20 | import SuperGraph from "./components/SuperGraph"; 21 | import EnsembleSuperGraph from "./components/SuperGraphEnsemble"; 22 | 23 | // Setup vuetify. 24 | import Vuetify from "vuetify/lib/framework"; 25 | Vue.use(Vuetify); 26 | const vuetify = new Vuetify({ 27 | icons: { 28 | iconfont: "mdiSvg" 29 | } 30 | }); 31 | 32 | import store from "./store"; 33 | 34 | const router = new Router({ 35 | routes: [ 36 | { 37 | path: "/", 38 | name: "Summary", 39 | component: Summary, 40 | props: true, 41 | }, 42 | { 43 | path: "/cct", 44 | name: "CCT", 45 | component: CCT, 46 | props: true 47 | }, 48 | { 49 | path: "/super_graph", 50 | name: "SuperGraph", 51 | component: SuperGraph, 52 | props: true 53 | }, 54 | { 55 | path: "/ensemble_super_graph", 56 | name: "EnsembleSuperGraph", 57 | component: EnsembleSuperGraph, 58 | props: true 59 | }, 60 | ] 61 | }); 62 | 63 | Vue.config.productionTip = false; 64 | Vue.use(BootstrapVue); 65 | Vue.use(Router); 66 | Vue.use(Vuetify); 67 | Vue.use(VueMaterial); 68 | 69 | new Vue({ 70 | store, 71 | render: h => h(App), 72 | el: "#app", 73 | router, 74 | components: { App }, 75 | vuetify, 76 | template: "" 77 | }); 78 | Vue.config.devtools = true; 79 | 80 | export default router; 81 | -------------------------------------------------------------------------------- /app/update_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Updating the distribution files" 4 | cd dist 5 | 6 | # rename 7 | cp js/app.*.js js/app.js 8 | cp js/app.*.js.map js/app.js.map 9 | cp js/chunk-vendors.*.js js/chunk-vendors.js 10 | cp js/chunk-vendors.*.js.map js/chunk-vendors.js.map 11 | cp css/app.*.css css/app.css 12 | cp css/chunk-vendors.*.css css/chunk-vendors.css 13 | 14 | # replace 15 | appjs='s/app\.[a-z0-9]*\.js/app.js/g' 16 | appcs='s/app\.[a-z0-9]*\.css/app.css/g' 17 | vndjs='s/chunk-vendors\.[a-z0-9]*\.js/chunk-vendors.js/g' 18 | vndcs='s/chunk-vendors\.[a-z0-9]*\.css/chunk-vendors.css/g' 19 | 20 | sed -i .bak -e ${appjs} -e ${appcs} -e ${vndjs} -e ${vndcs} index.html 21 | sed -i .bak -e ${appjs} js/app.js 22 | sed -i .bak -e ${appjs} js/app.js.map 23 | sed -i .bak -e ${vndjs} js/chunk-vendors.js 24 | sed -i .bak -e ${vndjs} js/chunk-vendors.js.map 25 | 26 | cd .. -------------------------------------------------------------------------------- /app/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transpileDependencies: [ 3 | "vuetify" 4 | ] 5 | }; 6 | -------------------------------------------------------------------------------- /callflow/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | """ 8 | Instantiates CallFlow's public API. 9 | """ 10 | from .version import __version__ # noqa 11 | from .utils.logger import init_logger, get_logger 12 | from .datastructures import SuperGraph, EnsembleGraph 13 | 14 | __all__ = [ 15 | "init_logger", 16 | "get_logger", 17 | "SuperGraph", 18 | "EnsembleGraph", 19 | ] 20 | 21 | 22 | # ------------------------------------------------------------------------------ 23 | ''' 24 | def load_ipython_extension(ipython): 25 | """IPython API entry point. 26 | Only intended to be called by the IPython runtime. 27 | See: 28 | https://ipython.readthedocs.io/en/stable/config/extensions/index.html 29 | """ 30 | # TODO: this needs to be fixed 31 | from .server.main import main 32 | from .server.notebook_server import load_ipython 33 | 34 | load_ipython(ipython, main) 35 | ''' 36 | 37 | # ------------------------------------------------------------------------------ 38 | -------------------------------------------------------------------------------- /callflow/algorithms/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """ 7 | CallFlow's Algorithm API. 8 | """ 9 | from .k_medoids import KMedoids 10 | from .bland_altman import BlandAltman_Plot 11 | from .deltacon_similarity import DLcon_Similarity 12 | from .wl_distance import WL_Distance 13 | 14 | __all__ = ["KMedoids", "DLcon_Similarity", "BlandAltman_Plot", "WL_Distance"] 15 | -------------------------------------------------------------------------------- /callflow/algorithms/bland_altman.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """ 7 | CallFlow's algorithm to compute the bland-altman plot. 8 | """ 9 | import numpy as np 10 | import matplotlib.cm as cm 11 | 12 | 13 | class BlandAltman_Plot: 14 | """ 15 | Bland altman plot calculation. 16 | A Bland–Altman plot or mean-difference plot to compare two executions by their mean runtime. 17 | """ 18 | 19 | def __init__(self): 20 | pass 21 | 22 | def compute(self, df_1, df_2, col, catcol): 23 | """ 24 | Compute the bland altman plot results. 25 | :param df_1: Dataframe 1 26 | :param df_2: Dataframe 2 27 | :param col: column to calculate the mean differences 28 | :param catcol: column to aggregate (usually by name or module column). 29 | :return: JSON { 30 | "name": catcol, // callsite 31 | "mean": mean, // mean of the combined data 32 | "diff": diff, absolute difference 33 | "color": colordict, // A linear space color map 34 | "md": md, mean difference 35 | "sd": sd, std. deviation 36 | } 37 | """ 38 | 39 | assert col in df_1 and catcol in df_1 40 | assert col in df_2 and catcol in df_2 41 | 42 | np_df_col_1 = np.asarray(df_1[col]) 43 | np_df_col_2 = np.asarray(df_2[col]) 44 | 45 | mean = np.mean([np_df_col_1, np_df_col_2], axis=0) 46 | diff = np_df_col_1 - np_df_col_2 47 | md = np.mean(diff) 48 | sd = np.std(diff, axis=0) 49 | 50 | categories = np.concatenate(np.unique(df_1[catcol]), np.unique(df_2[catcol])) 51 | colors = cm.rainbow(np.linspace(0, 1, len(categories))) 52 | colordict = list(dict(zip(categories, colors))) 53 | 54 | return { 55 | "axis": catcol, 56 | "mean": mean, 57 | "diff": diff, 58 | "color": colordict, 59 | "md": md, 60 | "sd": sd, 61 | } 62 | -------------------------------------------------------------------------------- /callflow/algorithms/deltacon_similarity.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | """ 6 | CallFlow's algorithm to differentiate two given CCTs. 7 | """ 8 | from math import sqrt 9 | import networkx as nx 10 | from numpy import square, trace, amax 11 | from scipy.sparse import identity 12 | from scipy.sparse import diags 13 | 14 | 15 | class DLcon_Similarity: 16 | """ 17 | DeltaCon similarity 18 | Refer the paper DELTACON: A Principled Massive-Graph Similarity Function 19 | https://arxiv.org/abs/1304.4657 20 | """ 21 | 22 | def __init__(self, g1, g2): 23 | """ 24 | 25 | :param g1: NetworkX graph 1 26 | :param g2: NetworkX graph 2 27 | """ 28 | 29 | nxg_e = nx.DiGraph() 30 | nxg_e.add_nodes_from(g1) 31 | nxg_e.add_nodes_from(g2) 32 | 33 | nxg_1 = nx.DiGraph() 34 | nxg_1.add_nodes_from(nxg_e) 35 | nxg_1.add_edges_from(g1.edges()) 36 | nxg_2 = nx.DiGraph() 37 | nxg_2.add_nodes_from(nxg_e) 38 | nxg_2.add_edges_from(g2.edges()) 39 | 40 | adj_1 = nx.adjacency_matrix(nxg_1) 41 | adj_2 = nx.adjacency_matrix(nxg_2) 42 | 43 | self.result = self.compute(adj_1, adj_2) 44 | 45 | def InverseMatrix(self, A): 46 | """ 47 | Calculate the inverse matrix of the adjacency matrix. 48 | 49 | :param A: Adjacency matrix 50 | :return: inverted matrix 51 | """ 52 | D = diags(sum(A).toarray(), [0]) 53 | c1 = trace(D.toarray()) + 2 54 | c2 = trace(square(D).toarray()) - 1 55 | 56 | h_h = sqrt((-c1 + sqrt(c1 * c1 + 4 * c2)) / (8 * c2)) 57 | a = 4 * h_h * h_h / (1 - 4 * h_h * h_h) 58 | c = 2 * h_h / (1 - 4 * h_h * h_h) 59 | M = c * A - a * D 60 | 61 | S = identity(A.shape[0]) 62 | mat = M 63 | power = 1 64 | while amax(M.toarray()) > 1e-09: 65 | if power < 7: 66 | S = S + mat 67 | mat = mat * M 68 | power += 1 69 | else: 70 | break 71 | return S 72 | 73 | def compute(self, A1, A2): 74 | """ 75 | Compare the adjacency matrixes and find similarity 76 | 77 | :param A1: Adjacency matrix for graph 1 78 | :param A2: Adjacency matrix for graph 2 79 | :return: similarity (0 < x < 1) 80 | """ 81 | S1 = self.InverseMatrix(A1) 82 | S2 = self.InverseMatrix(A2) 83 | d = 0 84 | for i in range(A1.shape[0]): 85 | for j in range(A1.shape[0]): 86 | d += (sqrt(S1.tocsr()[(i, j)]) - sqrt(S2.tocsr()[(i, j)])) ** 2 87 | d = sqrt(d) 88 | sim = 1 / (1 + d) 89 | return 1 - sim 90 | -------------------------------------------------------------------------------- /callflow/datastructures/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | """ 7 | CallFlow's data structure API. 8 | """ 9 | from .supergraph import SuperGraph # noqa 10 | from .ensemblegraph import EnsembleGraph # noqa 11 | from .metrics import * # noqa 12 | -------------------------------------------------------------------------------- /callflow/datastructures/ensemblegraph.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | """ 8 | CallFlow's ensemble super graph. 9 | """ 10 | from callflow import get_logger 11 | from .supergraph import SuperGraph 12 | 13 | from callflow.modules import Gradients 14 | 15 | LOGGER = get_logger(__name__) 16 | 17 | 18 | # ------------------------------------------------------------------------------ 19 | class EnsembleGraph(SuperGraph): 20 | "Ensemble SuperGraph Data structure" 21 | """ 22 | EnsembleGraph represents a unified graph and all components supergraphs. 23 | """ 24 | 25 | def __init__(self, name): 26 | """ 27 | Constructor to Ensemble SuperGraph 28 | :param name: tag for the ensemble 29 | """ 30 | super().__init__(name) 31 | 32 | self.supergraphs = {} 33 | self.dataframe = None 34 | self.nxg = None 35 | self.graph = None 36 | self.exc_metrics = [] 37 | self.inc_metrics = [] 38 | self.roots = [] # TODO: Populate this! 39 | self.module_df = None 40 | self.callsite_df = None 41 | 42 | def __str__(self): 43 | """ 44 | String representation for an ensemble super graph. 45 | :return: 46 | """ 47 | return ( 48 | f"EnsembleGraph<{self.name} of {len(self.supergraphs)} supergraphs; " 49 | f"df = {self.dataframe.shape}, cols = {list(self.dataframe.columns)}>" 50 | ) 51 | 52 | def __repr__(self): 53 | """ 54 | String representation for an ensemble super graph. 55 | :return: 56 | """ 57 | return self.__str__() 58 | 59 | def filter_by_datasets(self, selected_runs): 60 | """ 61 | Filter by the selected runs 62 | :param selected_runs: Array of dataset tag names. 63 | :return: None 64 | """ 65 | if selected_runs is not None: 66 | runs = selected_runs 67 | self.dataframe = self.df_filter_by_search_string("dataset", runs) 68 | else: 69 | runs = [name for name, sg in self.supergraphs.items()] 70 | self.dataframe = self.df_filter_by_search_string("dataset", runs) 71 | 72 | return runs 73 | 74 | def get_gradients(self, node, nbins): 75 | """ 76 | Getter to obtain the gradients of a node by the runtime metrics. 77 | """ 78 | assert self.name == "ensemble" 79 | 80 | return Gradients( 81 | self, node=node, bins=nbins, proxy_columns=self.proxy_columns 82 | ).result 83 | 84 | 85 | # ------------------------------------------------------------------------------ 86 | -------------------------------------------------------------------------------- /callflow/datastructures/metrics.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # some global enumerations 3 | # ------------------------------------------------------------------------------ 4 | 5 | # file formats that can be read 6 | FILE_FORMATS = ["hpctoolkit", "caliper", "caliper_json", "gprof", "literal", "lists"] 7 | 8 | # ------------------------------------------------------------------------------ 9 | TIME_COLUMNS = ["time (inc)", "time"] 10 | 11 | METRIC_PROXIES = { 12 | "time (inc)": [ 13 | "inclusive#time.duration", 14 | "REALTIME (sec) (I)", 15 | "1.CPUTIME (sec) (I)", 16 | ], 17 | "time": [ 18 | "sum#time.duration", 19 | "sum#sum#time.duration", 20 | "REALTIME (sec) (E)", 21 | "1.CPUTIME (sec) (E)", 22 | ], 23 | } 24 | 25 | # ------------------------------------------------------------------------------ 26 | -------------------------------------------------------------------------------- /callflow/layout/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """CallFlow's layout API.""" 7 | from .node_link import NodeLinkLayout 8 | from .sankey import SankeyLayout 9 | from .hierarchy import HierarchyLayout 10 | 11 | __all__ = ["NodeLinkLayout", "SankeyLayout", "HierarchyLayout"] 12 | -------------------------------------------------------------------------------- /callflow/modules/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """ 7 | CallFlow's operations API. 8 | """ 9 | from .boxplot import BoxPlot 10 | from .histogram import Histogram 11 | from .gradients import Gradients 12 | from .scatterplot import Scatterplot 13 | from .parameter_projection import ParameterProjection 14 | from .diff_view import DiffView 15 | 16 | __all__ = [ 17 | "BoxPlot", 18 | "Histogram", 19 | "Gradients", 20 | "Scatterplot", 21 | "ParameterProjection", 22 | "DiffView", 23 | ] 24 | -------------------------------------------------------------------------------- /callflow/modules/parameter_projection.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """ 7 | CallFlow operation to calculate 2-dimensional projections based on run's parameter information. 8 | """ 9 | 10 | import pandas as pd 11 | import numpy as np 12 | from sklearn import preprocessing 13 | from sklearn.manifold import TSNE, MDS 14 | from sklearn.cluster import KMeans 15 | 16 | from callflow.algorithms import KMedoids 17 | from callflow.datastructures.metrics import TIME_COLUMNS 18 | 19 | 20 | class ParameterProjection: 21 | """ 22 | Calculate Parameter projections using common projection techniques like MDS, t-SNE. 23 | """ 24 | 25 | def __init__(self, sg, selected_runs=None, n_cluster=3): 26 | """ 27 | Constructor for the 28 | 29 | :param sg: 30 | :param selected_runs: 31 | :param n_cluster: 32 | """ 33 | assert len(selected_runs) > 0 34 | assert isinstance(n_cluster, int) 35 | 36 | self.projection = "MDS" 37 | self.clustering = "k_means" 38 | self.n_cluster = int(n_cluster) 39 | self.proxy_columns = sg.proxy_columns 40 | self.time_columns = [self.proxy_columns.get(_, _) for _ in TIME_COLUMNS] 41 | 42 | if len(selected_runs) >= self.n_cluster: 43 | self.result = self.compute(sg, selected_runs) 44 | else: 45 | self.result = pd.DataFrame({}) 46 | 47 | def add_df_params(self, sg, dataset): 48 | """ 49 | Add information from the df about the dataset. 50 | :param dataset: dataset tag 51 | :return: dict comprising of "max_inclusive_time", "max_exclusive_time", and "rank_count". 52 | """ 53 | # TODO: Research what more properties can be appended to the dataframe. 54 | ret = {} 55 | ret["max_inclusive_time"] = sg.dataframe.loc[ 56 | sg.dataframe["dataset"] == dataset 57 | ][self.time_columns[0]].mean() 58 | ret["max_exclusive_time"] = sg.dataframe.loc[ 59 | sg.dataframe["dataset"] == dataset 60 | ][self.time_columns[1]].mean() 61 | ret["rank_count"] = len( 62 | sg.dataframe.loc[sg.dataframe["dataset"] == dataset]["rank"].unique() 63 | ) 64 | return ret 65 | 66 | def compute(self, sg, selected_runs): 67 | """ 68 | Compute the 2D projection of the the provided data after processing. 69 | 70 | :return: (Dict) { 71 | "dataset: 72 | " 73 | } 74 | """ 75 | rows = [] 76 | for dataset in selected_runs: 77 | df_params = self.add_df_params(sg, dataset) 78 | rows.append(df_params) 79 | 80 | df = pd.DataFrame(rows) 81 | 82 | # TODO: Remove all string columns from the dataframe. 83 | if "dataset" in df.columns: 84 | df = df.drop(columns=["dataset"]) 85 | x = df.values # returns a numpy array 86 | 87 | # Scale the values to value between 0 to 1 88 | min_max_scaler = preprocessing.MinMaxScaler() 89 | x_scaled = min_max_scaler.fit_transform(x) 90 | df = pd.DataFrame(x_scaled) 91 | X = np.vstack([df.values]) 92 | # X = np.vstack([df.values.tolist()]) 93 | 94 | random_number = 20150101 95 | if self.projection == "MDS": 96 | proj = MDS(random_state=random_number).fit_transform(X) 97 | 98 | elif self.projection == "TSNE": 99 | proj = TSNE(random_state=random_number).fit_transform(X) 100 | 101 | ret = pd.DataFrame(proj, columns=list("xy")) 102 | ret["dataset"] = selected_runs 103 | 104 | if self.clustering == "k_medoids": 105 | self.clusters = KMedoids(n_cluster=self.n_cluster) 106 | ret["label"] = self.clusters.fit(X) 107 | elif self.clustering == "k_means": 108 | self.clusters = KMeans( 109 | n_clusters=self.n_cluster, random_state=random_number 110 | ) 111 | ret["label"] = self.clusters.fit(X).labels_ 112 | 113 | return ret 114 | -------------------------------------------------------------------------------- /callflow/modules/scatterplot.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | """ 8 | CallFlow's operation to calculate runtime scatterplot (inclusive vs exclusive). 9 | """ 10 | 11 | import pandas as pd 12 | import numpy as np 13 | 14 | import callflow 15 | from callflow.datastructures.metrics import TIME_COLUMNS 16 | 17 | LOGGER = callflow.get_logger() 18 | 19 | 20 | class Scatterplot: 21 | """ 22 | Scatterplot plotting Inclusive vs Exclusive runtime. 23 | """ 24 | 25 | def __init__(self, sg, rel_sg=None, name="", ntype="", orientation=[]): 26 | """ 27 | Calculate Scatterplot for the callsite/module dataframe. 28 | 29 | :param sg: (CallFlow.SuperGraph) 30 | :param rel_sg: (CallFlow.SuperGraph) 31 | :param name: (str) Node's name 32 | :param ntype: (str) Node's type (e.g., module or callsite) 33 | :param orientation: (list(str, str)) Orientation of data (e.g., time vs time (inc)) 34 | """ 35 | assert isinstance(sg, callflow.SuperGraph) 36 | assert ntype in ["callsite", "module"] 37 | if rel_sg is not None: 38 | assert isinstance(rel_sg, callflow.SuperGraph) 39 | assert isinstance(orientation, list) 40 | assert all([o in TIME_COLUMNS for o in orientation]) 41 | 42 | self.time_columns = [sg.proxy_columns.get(_, _) for _ in TIME_COLUMNS] 43 | SCAT_TYPES = ["tgt"] 44 | if rel_sg is not None: 45 | SCAT_TYPES = ["tgt", "bkg"] 46 | self.result = {_: {} for _ in SCAT_TYPES} 47 | self.orientation = [sg.proxy_columns.get(_, _) for _ in orientation] 48 | self.node_type = ntype 49 | 50 | df = sg.get_aux_df(name, ntype) 51 | self.result["tgt"] = self.compute(df) 52 | 53 | if rel_sg is not None: 54 | rel_df = rel_sg.get_aux_df(name, ntype) 55 | self.result["bkg"] = self.compute(rel_df) 56 | 57 | def compute(self, df): 58 | assert isinstance(df, pd.DataFrame) 59 | 60 | ret = {_: {} for _ in TIME_COLUMNS} 61 | for tk, tv in zip(TIME_COLUMNS, self.time_columns): 62 | 63 | if self.node_type == "callsite": 64 | _data = df[tv].to_numpy() 65 | elif self.node_type == "module": 66 | _data = df.groupby(["rank"])[tv].mean().to_numpy() 67 | 68 | _min, _mean, _max = _data.min(), _data.mean(), _data.max() 69 | 70 | if "rank" in df.columns: 71 | _ranks = df["rank"].to_numpy() 72 | else: 73 | _ranks = np.array([]) 74 | 75 | ret[tv] = { 76 | "d": _data, 77 | "ranks": _ranks, 78 | "min": _min, 79 | "max": _max, 80 | "mean": _mean, 81 | } 82 | 83 | return ret 84 | 85 | def unpack(self): 86 | """ 87 | Unpack the data into JSON-supported format. 88 | 89 | :return: (JSON) 90 | """ 91 | ret = {} 92 | for scat_type in self.result.keys(): 93 | x = self.result[scat_type][self.orientation[0]] 94 | y = self.result[scat_type][self.orientation[1]] 95 | 96 | ret[scat_type] = { 97 | "x": x["d"].tolist(), 98 | "y": y["d"].tolist(), 99 | "ranks": x["ranks"].tolist(), 100 | "xMin": x["min"], 101 | "xMax": x["max"], 102 | "yMin": y["min"], 103 | "yMax": y["max"], 104 | "orientation": self.orientation, 105 | } 106 | return ret 107 | -------------------------------------------------------------------------------- /callflow/operations/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | """ 7 | CallFlow's operation API. 8 | """ 9 | from .filter import Filter 10 | from .group import Group 11 | from .unify import Unify 12 | from .config import Config 13 | from .regex_module_matcher import RegexModuleMatcher 14 | 15 | __all__ = ["Filter", "Group", "Unify", "Config", "RegexModuleMatcher"] 16 | 17 | # ------------------------------------------------------------------------------ 18 | -------------------------------------------------------------------------------- /callflow/operations/split_callee.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | """ 7 | CallFlow's operation to split by callee. 8 | """ 9 | import callflow 10 | 11 | LOGGER = callflow.get_logger(__name__) 12 | 13 | 14 | class SplitCallee: 15 | """ 16 | Split a callee if it is a module. 17 | """ 18 | 19 | def __init__(self, gf, callsites): 20 | """ 21 | 22 | :param gf: 23 | :param callsites: 24 | """ 25 | assert isinstance(gf, callflow.GraphFrame) 26 | assert "component_path" in gf.df.columns 27 | 28 | paths = self.callsite_paths(callsites) 29 | 30 | # module_group_df = gf.df.groupby(["module"]) 31 | module_name_group_df = gf.df.groupby(["module", "name"]) 32 | 33 | for path in paths: 34 | component_edges = self.create_source_targets(path["component_path"]) 35 | for idx, edge in enumerate(component_edges): 36 | module = edge["module"] 37 | 38 | # format module + '=' + callsite 39 | source = edge["source"] 40 | target = edge["target"] 41 | 42 | if not gf.nxg.has_edge(source, target): 43 | if idx == 0: 44 | source_callsite = source 45 | # source_df = module_group_df.get_group((module)) 46 | source_node_type = "super-node" 47 | else: 48 | source_callsite = source.split("=")[1] 49 | # source_df = module_name_group_df.get_group((module, source_callsite)) 50 | source_node_type = "component-node" 51 | 52 | target_callsite = target.split("=")[1] 53 | target_df = module_name_group_df.get_group( 54 | (module, target_callsite) 55 | ) 56 | target_node_type = "component-node" 57 | 58 | # source_weight = source_df["time (inc)"].max() 59 | target_weight = target_df["time (inc)"].max() 60 | 61 | edge_type = "normal" 62 | 63 | LOGGER.info(f"Adding edge: {source_callsite}, {target_callsite}") 64 | gf.nxg.add_node(source, attr_dict={"type": source_node_type}) 65 | gf.nxg.add_node(target, attr_dict={"type": target_node_type}) 66 | gf.nxg.add_edge( 67 | source, 68 | target, 69 | attr_dict=[ 70 | { 71 | "source_callsite": source_callsite, 72 | "target_callsite": target_callsite, 73 | "weight": target_weight, 74 | "edge_type": edge_type, 75 | } 76 | ], 77 | ) 78 | 79 | return gf 80 | 81 | def create_source_targets(self, component_path): 82 | """ 83 | 84 | :param component_path: 85 | :return: 86 | """ 87 | module = "" 88 | edges = [] 89 | for idx, callsite in enumerate(component_path): 90 | if idx == 0: 91 | module = component_path[0] 92 | edges.append( 93 | { 94 | "module": module, 95 | "source": module, 96 | "target": module + "=" + component_path[idx + 1], 97 | } 98 | ) 99 | pass 100 | elif idx == len(component_path) - 1: 101 | pass 102 | else: 103 | edges.append( 104 | { 105 | "module": module, 106 | "source": module + "=" + component_path[idx], 107 | "target": module + "=" + component_path[idx + 1], 108 | } 109 | ) 110 | 111 | return edges 112 | 113 | def callsite_paths(self, callsites): 114 | """ 115 | 116 | :param callsites: 117 | :return: 118 | """ 119 | from ast import literal_eval as make_list 120 | 121 | paths = [] 122 | for callsite in callsites: 123 | df = self.name_group_df.get_group(callsite) 124 | paths.append( 125 | { 126 | "group_path": make_list(df["group_path"].unique()[0]), 127 | "path": make_list(df["path"].unique()[0]), 128 | "component_path": make_list(df["component_path"].unique()[0]), 129 | } 130 | ) 131 | return paths 132 | -------------------------------------------------------------------------------- /callflow/tests/executable.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | 3 | 4 | def test_which(): 5 | assert shutil.which("callflow") 6 | -------------------------------------------------------------------------------- /callflow/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/callflow/utils/__init__.py -------------------------------------------------------------------------------- /callflow/utils/logger.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | import logging 8 | import colorlog 9 | from logging import getLogger as get_logger # noqa 10 | 11 | 12 | # ------------------------------------------------------------------------------ 13 | LOG_FMT = "%(asctime)s - %(name)s:%(funcName)s:%(lineno)s - %(levelname)s - %(message)s" 14 | LOG_COLORS = { 15 | "DEBUG": "cyan", 16 | "INFO": "green", 17 | "WARNING": "purple", 18 | "ERROR": "bold_red", 19 | "CRITICAL": "red", 20 | } 21 | 22 | 23 | # ------------------------------------------------------------------------------ 24 | def append_mem_usage(message): 25 | from .utils import get_memory_usage 26 | 27 | return f"[{get_memory_usage()}]: {message}" 28 | 29 | 30 | def _log_debug_with_memory(self, message, *args, **kws): 31 | self._log(logging.DEBUG, append_mem_usage(message), args, **kws) 32 | 33 | 34 | def _log_info_with_memory(self, message, *args, **kws): 35 | self._log(logging.INFO, append_mem_usage(message), args, **kws) 36 | 37 | 38 | def _log_warning_with_memory(self, message, *args, **kws): 39 | self._log(logging.WARNING, append_mem_usage(message), args, **kws) 40 | 41 | 42 | def _log_error_with_memory(self, message, *args, **kws): 43 | self._log(logging.ERROR, append_mem_usage(message), args, **kws) 44 | 45 | 46 | def _log_critical_with_memory(self, message, *args, **kws): 47 | self._log(logging.CRITICAL, append_mem_usage(message), args, **kws) 48 | 49 | 50 | # ------------------------------------------------------------------------------ 51 | # ------------------------------------------------------------------------------ 52 | def init_logger(**kwargs): 53 | 54 | # extract the logging parameters (defaults given) 55 | level = int(kwargs.get("level", 2)) 56 | do_color = str(kwargs.get("color", True)) 57 | file = str(kwargs.get("file", "")) 58 | mem_usage = bool(kwargs.get("mem_usage", False)) 59 | 60 | # -------------------------------------------------------------------------- 61 | # get logging level in "logging" format 62 | assert 1 <= level <= 5 63 | if level == 1: 64 | level = logging.DEBUG 65 | elif level == 2: 66 | level = logging.INFO 67 | elif level == 3: 68 | level = logging.WARN 69 | elif level == 4: 70 | level = logging.ERROR 71 | elif level == 5: 72 | level = logging.CRITICAL 73 | 74 | # ------------------------------------------------------------------------- 75 | # get logging format 76 | # here, the initialization of the format doesnt depend upon "level" 77 | # create the actual formatter 78 | if do_color and file == "": 79 | formatter = colorlog.ColoredFormatter( 80 | "%(log_color)s" + LOG_FMT, log_colors=LOG_COLORS 81 | ) 82 | else: 83 | formatter = logging.Formatter(LOG_FMT) 84 | 85 | # create a handler 86 | if file == "": 87 | sh = logging.StreamHandler() 88 | sh.setFormatter(formatter) 89 | else: 90 | sh = logging.FileHandler(file) 91 | sh.setFormatter(formatter) 92 | 93 | # finally, create a logger 94 | logger = logging.getLogger() # root logger 95 | logger.setLevel(level) 96 | logger.addHandler(sh) 97 | 98 | # -------------------------------------------------------------------------- 99 | # if we want to show the memory usage 100 | if mem_usage: 101 | logging.Logger.info = _log_info_with_memory 102 | logging.Logger.debug = _log_debug_with_memory 103 | logging.Logger.warning = _log_warning_with_memory 104 | logging.Logger.error = _log_error_with_memory 105 | logging.Logger.critical = _log_critical_with_memory 106 | 107 | return 108 | # -------------------------------------------------------------------------- 109 | # Print the level of logging. 110 | logger.debug("Enabled") 111 | logger.info("Enabled") 112 | logger.warning("Enabled") 113 | logger.error("Enabled") 114 | logger.critical("Enabled") 115 | 116 | 117 | # ------------------------------------------------------------------------------ 118 | -------------------------------------------------------------------------------- /callflow/utils/nxg.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | 8 | def nxg_info(nxg): 9 | return f"Nodes: {len(nxg.nodes())}, edges: {len(nxg.edges())}." 10 | -------------------------------------------------------------------------------- /callflow/utils/sanitizer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | import os 7 | import hatchet as ht 8 | import datetime 9 | 10 | # import arrow 11 | 12 | import callflow 13 | 14 | LOGGER = callflow.get_logger(__name__) 15 | 16 | 17 | # ------------------------------------------------------------------------------ 18 | # ------------------------------------------------------------------------------ 19 | class Sanitizer: 20 | 21 | _KNOWN_TYPES = ["function", "statement", "loop", "region"] 22 | 23 | @staticmethod 24 | def sanitize(_: str): 25 | return os.path.basename(_) if _ is not None else "Unknown" 26 | 27 | @staticmethod 28 | def from_htframe(_: ht.frame.Frame): 29 | assert isinstance(_, ht.frame.Frame) 30 | 31 | _type = _["type"] 32 | assert _type in Sanitizer._KNOWN_TYPES 33 | 34 | if _type in ["function", "region"]: 35 | return Sanitizer.sanitize(_.get("name", "Unknown")) 36 | 37 | elif _type == "statement": 38 | _file, _line = _["file"], str(_["line"]) 39 | return Sanitizer.sanitize(_file) + ":" + _line 40 | 41 | elif _type == "loop": 42 | _file, _line = _["file"], str(_["line"]) 43 | return "Loop@" + Sanitizer.sanitize(_file) + ":" + _line 44 | 45 | @staticmethod 46 | def fmt_time(tstamp): 47 | """ 48 | Format according to daniel's data format. 49 | 50 | e.g., laghos_2020-12-04_01-04-11 => 2020-12-04 01:04:11 51 | """ 52 | fmt_from = "%Y-%m-%d_%H-%M-%S" 53 | fmt_to = "%Y-%m-%d %H:%M:%S" 54 | 55 | try: 56 | dt = datetime.datetime.strptime(tstamp, fmt_from) 57 | return datetime.datetime.strftime(dt, fmt_to) 58 | except ValueError as e: 59 | LOGGER.warn("Not a valid timestamp.") 60 | LOGGER.warn(e) 61 | return tstamp 62 | 63 | def datetime_to_fmt(datetime): 64 | fmt_to = "%Y-%m-%d %H:%M:%S" 65 | return datetime.strftime(fmt_to) 66 | 67 | @staticmethod 68 | def fmt_timestr_to_datetime(string): 69 | fmt_to = "%Y-%m-%d %H:%M:%S" 70 | 71 | return datetime.datetime.strptime(string, fmt_to) 72 | 73 | 74 | # ------------------------------------------------------------------------------ 75 | -------------------------------------------------------------------------------- /callflow/utils/timer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | from collections import OrderedDict 8 | from contextlib import contextmanager 9 | from datetime import datetime 10 | from io import StringIO 11 | 12 | 13 | # ------------------------------------------------------------------------------ 14 | # ------------------------------------------------------------------------------ 15 | class Timer(object): 16 | """ 17 | Simple phase timer with a context manager. 18 | """ 19 | 20 | def __init__(self): 21 | self._phase = None 22 | self._start_time = None 23 | self._times = OrderedDict() 24 | 25 | def start_phase(self, phase): 26 | now = datetime.now() 27 | delta = None 28 | 29 | if self._phase: 30 | delta = now - self._start_time 31 | self._times[self._phase] = delta 32 | 33 | self._phase = phase 34 | self._start_time = now 35 | return delta 36 | 37 | def end_phase(self): 38 | assert self._phase and self._start_time 39 | 40 | now = datetime.now() 41 | delta = now - self._start_time 42 | self._times[self._phase] = delta 43 | 44 | self._phase = None 45 | self._start_time = None 46 | 47 | def __str__(self): 48 | out = StringIO() 49 | out.write(u"Times:\n") 50 | for phase, delta in self._times.items(): 51 | out.write(u" %-20s %.2fs\n" % (phase + ":", delta.total_seconds())) 52 | return out.getvalue() 53 | 54 | @contextmanager 55 | def phase(self, name): 56 | self.start_phase(name) 57 | yield 58 | self.end_phase() 59 | 60 | 61 | # ------------------------------------------------------------------------------ 62 | -------------------------------------------------------------------------------- /callflow/version.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # ------------------------------------------------------------------------------ 6 | 7 | """ 8 | Version information 9 | """ 10 | __version_info__ = ("1", "3", "0") 11 | __version__ = ".".join(__version_info__) 12 | 13 | # ------------------------------------------------------------------------------ 14 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | # Datasets for testing CallFlow. 2 | 3 | All the listed datasets are provided by [Hatchet](https://github.com/LLNL/hatchet/tree/develop/hatchet/tests/data). 4 | 5 | 6 | ## Directory Structure 7 | Callflow currently, supports two formats, [hpctoolkit](http://hpctoolkit.org/) and [caliper](www.github.com/LLNL/caliper). 8 | 9 | Make sure the directory structure for each format is as shown below. 10 | 11 | ### HPCToolkit 12 | For HPCToolkit data, make sure there is an experiment.xml file and all the [metric-db](http://hpctoolkit.org/man/hpcprof.html) files are individual files. 13 | 14 | ``` 15 | {$CALLFLOW_PATH}/data/{hpctoolkit_dataset} 16 | .../experiment.xml 17 | .../thread-001.metric-db 18 | .../thread-002.metric-db 19 | .../thread-003.metric-db 20 | ... 21 | ``` 22 | 23 | ### Caliper 24 | For caliper data, make sure you generate using `caliper-json` format. 25 | 26 | ``` 27 | {$CALLFLOW_PATH}/data/{caliper_dataset} 28 | .../data.json 29 | .../ 30 | 31 | ``` 32 | 33 | # Configuration file. 34 | - Once the data is in place, create a `config.callflow.json` file inside the data directory. 35 | 36 | - `config.callflow.json` uses JSON formatting to help pre-process the datasets. 37 | 38 | 39 | - The "scheme" key determines how the preprocessing operations are performed (i.e., filtering, grouping operations) using a scheme. 40 | 41 | 42 | ``` 43 | { 44 | "run_name": "{run_name}", // Name of the experiment. 45 | "save_path": "{data/run_name/.callflow}", // File path to save callflow generated files. 46 | "datasets": [ 47 | { 48 | "name": "dataset-1", // name of dataset 49 | "path": "data/run_name/dataset_1}", // path to dataset 1 50 | "format": "{profile_format}" // HPCToolkit|Caliper 51 | }, 52 | { 53 | "name": "dataset-1", // name of dataset 54 | "path": "data/run_name/dataset_1}", // path to dataset 1 55 | "format": "{profile_format}" // HPCToolkit|Caliper 56 | }, 57 | ... 58 | ], 59 | "scheme": { 60 | "filter_by": "{filter_metric", // time (inc)|time 61 | "filter_perc": "{filter_percentage}", 62 | "group_by": "{group_metric", // name for CallGraph and module for SuperGraph. 63 | "module_map": { 64 | "module-1": [ 65 | "callsite-1", 66 | "callsite-2", 67 | ... 68 | ], 69 | "module-2": [ 70 | ... 71 | ], 72 | ... 73 | "module-n": [ 74 | ... 75 | ] 76 | 77 | }, 78 | } 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /data/caliper-lulesh-cali/lulesh-annotation-profile.cali: -------------------------------------------------------------------------------- 1 | __rec=node,id=24,attr=10,data=588,parent=3 2 | __rec=node,id=27,attr=8,data=cali.channel,parent=24 3 | __rec=node,id=25,attr=8,data=cali.caliper.version,parent=24 4 | __rec=node,id=26,attr=25,data=2.2.0-dev 5 | __rec=node,id=28,attr=27,data=default,parent=26 6 | __rec=node,id=96,attr=10,data=21,parent=5 7 | __rec=node,id=97,attr=8,data=min#time.duration,parent=96 8 | __rec=node,id=105,attr=8,data=max#time.duration,parent=96 9 | __rec=node,id=111,attr=8,data=sum#time.duration,parent=96 10 | __rec=node,id=117,attr=8,data=avg#time.duration,parent=96 11 | __rec=node,id=147,attr=10,data=21,parent=1 12 | __rec=node,id=148,attr=8,data=count,parent=147 13 | __rec=ctx,ref=28,attr=97=105=111=117=148,data=0.001297=0.001297=0.001297=0.001297=1 14 | __rec=node,id=19,attr=10,data=268,parent=3 15 | __rec=node,id=20,attr=8,data=function,parent=19 16 | __rec=node,id=155,attr=20,data=main,parent=28 17 | __rec=ctx,ref=155,attr=97=105=111=117=148,data=0.000285=0.024836=0.025121=0.012561=2 18 | __rec=node,id=21,attr=8,data=loop,parent=19 19 | __rec=node,id=165,attr=21,data=lulesh.cycle,parent=155 20 | __rec=ctx,ref=165,attr=97=105=111=117=148,data=0.000004=0.000015=0.000206=0.000005=41 21 | __rec=node,id=166,attr=20,data=TimeIncrement,parent=165 22 | __rec=ctx,ref=166,attr=97=105=111=117=148,data=0.000008=0.000022=0.000102=0.000010=10 23 | __rec=node,id=167,attr=20,data=LagrangeLeapFrog,parent=165 24 | __rec=ctx,ref=167,attr=97=105=111=117=148,data=0.000004=0.000021=0.000226=0.000006=40 25 | __rec=node,id=168,attr=20,data=LagrangeNodal,parent=167 26 | __rec=ctx,ref=168,attr=97=105=111=117=148,data=0.000003=0.001466=0.012400=0.000620=20 27 | __rec=node,id=169,attr=20,data=CalcForceForNodes,parent=168 28 | __rec=ctx,ref=169,attr=97=105=111=117=148,data=0.000004=0.000385=0.001854=0.000093=20 29 | __rec=node,id=170,attr=20,data=CalcVolumeForceForElems,parent=169 30 | __rec=ctx,ref=170,attr=97=105=111=117=148,data=0.000007=0.000241=0.001841=0.000061=30 31 | __rec=node,id=171,attr=20,data=IntegrateStressForElems,parent=170 32 | __rec=ctx,ref=171,attr=97=105=111=117=148,data=0.005258=0.006681=0.056681=0.005668=10 33 | __rec=node,id=172,attr=20,data=CalcHourglassControlForElems,parent=170 34 | __rec=ctx,ref=172,attr=97=105=111=117=148,data=0.000675=0.006053=0.059643=0.002982=20 35 | __rec=node,id=173,attr=20,data=CalcFBHourglassForceForElems,parent=172 36 | __rec=ctx,ref=173,attr=97=105=111=117=148,data=0.007265=0.008769=0.080608=0.008061=10 37 | __rec=node,id=174,attr=20,data=LagrangeElements,parent=167 38 | __rec=ctx,ref=174,attr=97=105=111=117=148,data=0.000004=0.000146=0.001367=0.000034=40 39 | __rec=node,id=175,attr=20,data=CalcLagrangeElements,parent=174 40 | __rec=ctx,ref=175,attr=97=105=111=117=148,data=0.000004=0.000368=0.002862=0.000143=20 41 | __rec=node,id=176,attr=20,data=CalcKinematicsForElems,parent=175 42 | __rec=ctx,ref=176,attr=97=105=111=117=148,data=0.004971=0.006349=0.055700=0.005570=10 43 | __rec=node,id=177,attr=20,data=CalcQForElems,parent=174 44 | __rec=ctx,ref=177,attr=97=105=111=117=148,data=0.000227=0.003135=0.031685=0.001584=20 45 | __rec=node,id=178,attr=20,data=CalcMonotonicQForElems,parent=177 46 | __rec=ctx,ref=178,attr=97=105=111=117=148,data=0.001310=0.001522=0.014334=0.001433=10 47 | __rec=node,id=179,attr=20,data=ApplyMaterialPropertiesForElems,parent=174 48 | __rec=ctx,ref=179,attr=97=105=111=117=148,data=0.000004=0.000219=0.002410=0.000020=120 49 | __rec=node,id=180,attr=20,data=EvalEOSForElems,parent=179 50 | __rec=ctx,ref=180,attr=97=105=111=117=148,data=0.000016=0.000282=0.044917=0.000098=460 51 | __rec=node,id=181,attr=20,data=CalcEnergyForElems,parent=180 52 | __rec=ctx,ref=181,attr=97=105=111=117=148,data=0.000051=0.001470=0.095906=0.000274=350 53 | __rec=node,id=182,attr=20,data=CalcTimeConstraintsForElems,parent=167 54 | __rec=ctx,ref=182,attr=97=105=111=117=148,data=0.000413=0.000518=0.004628=0.000463=10 55 | __rec=globals,ref=28 56 | -------------------------------------------------------------------------------- /data/caliper-simple-cali/caliper-simple.cali: -------------------------------------------------------------------------------- 1 | __rec=node,id=24,attr=10,data=588,parent=3 2 | __rec=node,id=27,attr=8,data=cali.channel,parent=24 3 | __rec=node,id=25,attr=8,data=cali.caliper.version,parent=24 4 | __rec=node,id=26,attr=25,data=2.2.0-dev 5 | __rec=node,id=28,attr=27,data=default,parent=26 6 | __rec=node,id=96,attr=10,data=21,parent=5 7 | __rec=node,id=97,attr=8,data=min#time.duration,parent=96 8 | __rec=node,id=105,attr=8,data=max#time.duration,parent=96 9 | __rec=node,id=111,attr=8,data=sum#time.duration,parent=96 10 | __rec=node,id=117,attr=8,data=avg#time.duration,parent=96 11 | __rec=node,id=147,attr=10,data=21,parent=1 12 | __rec=node,id=148,attr=8,data=count,parent=147 13 | __rec=ctx,ref=28,attr=97=105=111=117=148,data=0.001297=0.001297=0.001297=0.001297=1 14 | __rec=node,id=19,attr=10,data=268,parent=3 15 | __rec=node,id=20,attr=8,data=function,parent=19 16 | __rec=node,id=155,attr=20,data=main,parent=28 17 | __rec=ctx,ref=155,attr=97=105=111=117=148,data=0.000285=0.024836=0.025121=0.012561=2 18 | __rec=node,id=21,attr=8,data=loop,parent=19 19 | __rec=node,id=165,attr=21,data=lulesh.cycle,parent=155 20 | __rec=ctx,ref=165,attr=97=105=111=117=148,data=0.000004=0.000015=0.000206=0.000005=41 21 | __rec=node,id=166,attr=20,data=TimeIncrement,parent=165 22 | __rec=ctx,ref=166,attr=97=105=111=117=148,data=0.000008=0.000022=0.000102=0.000010=10 23 | __rec=node,id=167,attr=20,data=LagrangeLeapFrog,parent=165 24 | __rec=ctx,ref=167,attr=97=105=111=117=148,data=0.000004=0.000021=0.000226=0.000006=40 25 | __rec=node,id=168,attr=20,data=LagrangeNodal,parent=167 26 | __rec=ctx,ref=168,attr=97=105=111=117=148,data=0.000003=0.001466=0.012400=0.000620=20 27 | __rec=node,id=169,attr=20,data=CalcForceForNodes,parent=168 28 | __rec=ctx,ref=169,attr=97=105=111=117=148,data=0.000004=0.000385=0.001854=0.000093=20 29 | __rec=node,id=170,attr=20,data=CalcVolumeForceForElems,parent=169 30 | __rec=ctx,ref=170,attr=97=105=111=117=148,data=0.000007=0.000241=0.001841=0.000061=30 31 | __rec=node,id=171,attr=20,data=IntegrateStressForElems,parent=170 32 | __rec=ctx,ref=171,attr=97=105=111=117=148,data=0.005258=0.006681=0.056681=0.005668=10 33 | __rec=node,id=172,attr=20,data=CalcHourglassControlForElems,parent=170 34 | __rec=ctx,ref=172,attr=97=105=111=117=148,data=0.000675=0.006053=0.059643=0.002982=20 35 | __rec=node,id=173,attr=20,data=CalcFBHourglassForceForElems,parent=172 36 | __rec=ctx,ref=173,attr=97=105=111=117=148,data=0.007265=0.008769=0.080608=0.008061=10 37 | __rec=node,id=174,attr=20,data=LagrangeElements,parent=167 38 | __rec=ctx,ref=174,attr=97=105=111=117=148,data=0.000004=0.000146=0.001367=0.000034=40 39 | __rec=node,id=175,attr=20,data=CalcLagrangeElements,parent=174 40 | __rec=ctx,ref=175,attr=97=105=111=117=148,data=0.000004=0.000368=0.002862=0.000143=20 41 | __rec=node,id=176,attr=20,data=CalcKinematicsForElems,parent=175 42 | __rec=ctx,ref=176,attr=97=105=111=117=148,data=0.004971=0.006349=0.055700=0.005570=10 43 | __rec=node,id=177,attr=20,data=CalcQForElems,parent=174 44 | __rec=ctx,ref=177,attr=97=105=111=117=148,data=0.000227=0.003135=0.031685=0.001584=20 45 | __rec=node,id=178,attr=20,data=CalcMonotonicQForElems,parent=177 46 | __rec=ctx,ref=178,attr=97=105=111=117=148,data=0.001310=0.001522=0.014334=0.001433=10 47 | __rec=node,id=179,attr=20,data=ApplyMaterialPropertiesForElems,parent=174 48 | __rec=ctx,ref=179,attr=97=105=111=117=148,data=0.000004=0.000219=0.002410=0.000020=120 49 | __rec=node,id=180,attr=20,data=EvalEOSForElems,parent=179 50 | __rec=ctx,ref=180,attr=97=105=111=117=148,data=0.000016=0.000282=0.044917=0.000098=460 51 | __rec=node,id=181,attr=20,data=CalcEnergyForElems,parent=180 52 | __rec=ctx,ref=181,attr=97=105=111=117=148,data=0.000051=0.001470=0.095906=0.000274=350 53 | __rec=node,id=182,attr=20,data=CalcTimeConstraintsForElems,parent=167 54 | __rec=ctx,ref=182,attr=97=105=111=117=148,data=0.000413=0.000518=0.004628=0.000463=10 55 | __rec=globals,ref=28 56 | -------------------------------------------------------------------------------- /data/caliper-simple-json/caliper-simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | [ 0.001297, 0.001297, null ], 4 | [ 0.492491, 0.025327, 0 ], 5 | [ 0.000102, 0.000102, 1 ], 6 | [ 0.467062, 0.000226, 2 ], 7 | [ 0.213027, 0.012400, 3 ], 8 | [ 0.200627, 0.001854, 4 ], 9 | [ 0.198773, 0.001841, 5 ], 10 | [ 0.056681, 0.056681, 6 ], 11 | [ 0.140251, 0.059643, 7 ], 12 | [ 0.080608, 0.080608, 8 ], 13 | [ 0.249181, 0.001367, 9 ], 14 | [ 0.058562, 0.002862, 10 ], 15 | [ 0.055700, 0.055700, 11 ], 16 | [ 0.046019, 0.031685, 12 ], 17 | [ 0.014334, 0.014334, 13 ], 18 | [ 0.143233, 0.002410, 14 ], 19 | [ 0.140823, 0.044917, 15 ], 20 | [ 0.095906, 0.095906, 16 ], 21 | [ 0.004628, 0.004628, 17 ] 22 | ], 23 | "columns": [ "inclusive#sum#time.duration", "sum#time.duration", "path" ], 24 | "column_metadata": [ { "is_value": true }, { "is_value": true }, { "is_value": false } ], 25 | "nodes": [ { "label": "main", "column": "path" }, { "label": "TimeIncrement", "column": "path", "parent": 0 }, { "label": "LagrangeLeapFrog", "column": "path", "parent": 0 }, { "label": "LagrangeNodal", "column": "path", "parent": 2 }, { "label": "CalcForceForNodes", "column": "path", "parent": 3 }, { "label": "CalcVolumeForceForElems", "column": "path", "parent": 4 }, { "label": "IntegrateStressForElems", "column": "path", "parent": 5 }, { "label": "CalcHourglassControlForElems", "column": "path", "parent": 5 }, { "label": "CalcFBHourglassForceForElems", "column": "path", "parent": 7 }, { "label": "LagrangeElements", "column": "path", "parent": 2 }, { "label": "CalcLagrangeElements", "column": "path", "parent": 9 }, { "label": "CalcKinematicsForElems", "column": "path", "parent": 10 }, { "label": "CalcQForElems", "column": "path", "parent": 9 }, { "label": "CalcMonotonicQForElems", "column": "path", "parent": 12 }, { "label": "ApplyMaterialPropertiesForElems", "column": "path", "parent": 9 }, { "label": "EvalEOSForElems", "column": "path", "parent": 14 }, { "label": "CalcEnergyForElems", "column": "path", "parent": 15 }, { "label": "CalcTimeConstraintsForElems", "column": "path", "parent": 2 } ], 26 | "cali.channel": "default", 27 | "cali.caliper.version": "2.2.0-dev" 28 | } 29 | -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000000-000-a8c00471-152577-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000000-000-a8c00471-152577-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000000-001-a8c00471-152577-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000000-001-a8c00471-152577-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000001-000-a8c00471-152578-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000001-000-a8c00471-152578-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000001-001-a8c00471-152578-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000001-001-a8c00471-152578-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000002-000-a8c00471-152579-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000002-000-a8c00471-152579-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000002-001-a8c00471-152579-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000002-001-a8c00471-152579-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000003-000-a8c00471-152580-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000003-000-a8c00471-152580-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000003-001-a8c00471-152580-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000003-001-a8c00471-152580-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000004-000-a8c00471-152581-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000004-000-a8c00471-152581-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000004-001-a8c00471-152581-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000004-001-a8c00471-152581-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000005-000-a8c00471-152582-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000005-000-a8c00471-152582-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000005-001-a8c00471-152582-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000005-001-a8c00471-152582-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000006-000-a8c00471-152583-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000006-000-a8c00471-152583-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000006-001-a8c00471-152583-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000006-001-a8c00471-152583-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000007-000-a8c00471-152584-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000007-000-a8c00471-152584-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000007-001-a8c00471-152584-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000007-001-a8c00471-152584-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000008-000-a8c00471-152585-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000008-000-a8c00471-152585-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000008-001-a8c00471-152585-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000008-001-a8c00471-152585-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000009-000-a8c00471-152586-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000009-000-a8c00471-152586-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/1.osu_allgather-000009-001-a8c00471-152586-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-allgather-database/1.osu_allgather-000009-001-a8c00471-152586-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-allgather-database/src/osu_allgather.c: -------------------------------------------------------------------------------- 1 | #define BENCHMARK "OSU MPI%s Allgather Latency Test" 2 | /* 3 | * Copyright (C) 2002-2019 the Network-Based Computing Laboratory 4 | * (NBCL), The Ohio State University. 5 | * 6 | * Contact: Dr. D. K. Panda (panda@cse.ohio-state.edu) 7 | * 8 | * For detailed copyright and licensing information, please refer to the 9 | * copyright file COPYRIGHT in the top level OMB directory. 10 | */ 11 | #include 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | int i, numprocs, rank, size; 16 | double latency = 0.0, t_start = 0.0, t_stop = 0.0; 17 | double timer=0.0; 18 | double avg_time = 0.0, max_time = 0.0, min_time = 0.0; 19 | char *sendbuf, *recvbuf; 20 | int po_ret; 21 | size_t bufsize; 22 | options.bench = COLLECTIVE; 23 | options.subtype = LAT; 24 | 25 | set_header(HEADER); 26 | set_benchmark_name("osu_allgather"); 27 | po_ret = process_options(argc, argv); 28 | 29 | if (PO_OKAY == po_ret && NONE != options.accel) { 30 | if (init_accel()) { 31 | fprintf(stderr, "Error initializing device\n"); 32 | exit(EXIT_FAILURE); 33 | } 34 | } 35 | 36 | MPI_CHECK(MPI_Init(&argc, &argv)); 37 | MPI_CHECK(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 38 | MPI_CHECK(MPI_Comm_size(MPI_COMM_WORLD, &numprocs)); 39 | 40 | switch (po_ret) { 41 | case PO_BAD_USAGE: 42 | print_bad_usage_message(rank); 43 | MPI_CHECK(MPI_Finalize()); 44 | exit(EXIT_FAILURE); 45 | case PO_HELP_MESSAGE: 46 | print_help_message(rank); 47 | MPI_CHECK(MPI_Finalize()); 48 | exit(EXIT_SUCCESS); 49 | case PO_VERSION_MESSAGE: 50 | print_version_message(rank); 51 | MPI_CHECK(MPI_Finalize()); 52 | exit(EXIT_SUCCESS); 53 | case PO_OKAY: 54 | break; 55 | } 56 | 57 | if(numprocs < 2) { 58 | if (rank == 0) { 59 | fprintf(stderr, "This test requires at least two processes\n"); 60 | } 61 | 62 | MPI_CHECK(MPI_Finalize()); 63 | exit(EXIT_FAILURE); 64 | } 65 | 66 | if ((options.max_message_size * numprocs) > options.max_mem_limit) { 67 | options.max_message_size = options.max_mem_limit / numprocs; 68 | } 69 | 70 | if (allocate_memory_coll((void**)&sendbuf, options.max_message_size, options.accel)) { 71 | fprintf(stderr, "Could Not Allocate Memory [rank %d]\n", rank); 72 | MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE)); 73 | } 74 | set_buffer(sendbuf, options.accel, 1, options.max_message_size); 75 | 76 | bufsize = options.max_message_size * numprocs; 77 | if (allocate_memory_coll((void**)&recvbuf, bufsize, 78 | options.accel)) { 79 | fprintf(stderr, "Could Not Allocate Memory [rank %d]\n", rank); 80 | MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE)); 81 | } 82 | set_buffer(recvbuf, options.accel, 0, bufsize); 83 | 84 | print_preamble(rank); 85 | 86 | for(size=options.min_message_size; size <= options.max_message_size; size *= 2) { 87 | 88 | if(size > LARGE_MESSAGE_SIZE) { 89 | options.skip = options.skip_large; 90 | options.iterations = options.iterations_large; 91 | } 92 | 93 | MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD)); 94 | timer=0.0; 95 | for(i=0; i < options.iterations + options.skip ; i++) { 96 | t_start = MPI_Wtime(); 97 | MPI_CHECK(MPI_Allgather( sendbuf, size, MPI_CHAR, 98 | recvbuf, size, MPI_CHAR, MPI_COMM_WORLD )); 99 | 100 | t_stop = MPI_Wtime(); 101 | 102 | if(i >= options.skip) { 103 | timer+= t_stop-t_start; 104 | } 105 | MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD)); 106 | 107 | } 108 | 109 | MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD)); 110 | 111 | latency = (double)(timer * 1e6) / options.iterations; 112 | 113 | MPI_CHECK(MPI_Reduce(&latency, &min_time, 1, MPI_DOUBLE, MPI_MIN, 0, 114 | MPI_COMM_WORLD)); 115 | MPI_CHECK(MPI_Reduce(&latency, &max_time, 1, MPI_DOUBLE, MPI_MAX, 0, 116 | MPI_COMM_WORLD)); 117 | MPI_CHECK(MPI_Reduce(&latency, &avg_time, 1, MPI_DOUBLE, MPI_SUM, 0, 118 | MPI_COMM_WORLD)); 119 | avg_time = avg_time/numprocs; 120 | 121 | print_stats(rank, size, avg_time, min_time, max_time); 122 | MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD)); 123 | } 124 | 125 | free_buffer(sendbuf, options.accel); 126 | free_buffer(recvbuf, options.accel); 127 | 128 | MPI_CHECK(MPI_Finalize()); 129 | 130 | if (NONE != options.accel) { 131 | if (cleanup_accel()) { 132 | fprintf(stderr, "Error cleaning up device\n"); 133 | exit(EXIT_FAILURE); 134 | } 135 | } 136 | 137 | return EXIT_SUCCESS; 138 | } 139 | /* vi: set sw=4 sts=4 tw=80: */ 140 | -------------------------------------------------------------------------------- /data/hpctoolkit-cpi-database/1.cpi-000000-000-a8c00270-160443-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-cpi-database/1.cpi-000000-000-a8c00270-160443-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-cpi-database/1.cpi-000001-000-a8c00270-160444-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-cpi-database/1.cpi-000001-000-a8c00270-160444-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-cpi-database/1.cpi-000002-000-a8c00270-160445-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-cpi-database/1.cpi-000002-000-a8c00270-160445-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-cpi-database/1.cpi-000003-000-a8c00270-160446-0.metric-db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/data/hpctoolkit-cpi-database/1.cpi-000003-000-a8c00270-160446-0.metric-db -------------------------------------------------------------------------------- /data/hpctoolkit-cpi-database/src/cpi.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ 2 | /* 3 | * (C) 2001 by Argonne National Laboratory. 4 | * See COPYRIGHT in top-level directory. 5 | */ 6 | 7 | #include "mpi.h" 8 | #include 9 | #include 10 | 11 | double f(double); 12 | 13 | double f(double a) 14 | { 15 | return (4.0 / (1.0 + a*a)); 16 | } 17 | 18 | int main(int argc,char *argv[]) 19 | { 20 | int n, myid, numprocs, i; 21 | double PI25DT = 3.141592653589793238462643; 22 | double mypi, pi, h, sum, x; 23 | double startwtime = 0.0, endwtime; 24 | int namelen; 25 | char processor_name[MPI_MAX_PROCESSOR_NAME]; 26 | 27 | MPI_Init(&argc,&argv); 28 | MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 29 | MPI_Comm_rank(MPI_COMM_WORLD,&myid); 30 | MPI_Get_processor_name(processor_name,&namelen); 31 | 32 | fprintf(stdout,"Process %d of %d is on %s\n", 33 | myid, numprocs, processor_name); 34 | fflush(stdout); 35 | 36 | n = 10000; /* default # of rectangles */ 37 | if (myid == 0) 38 | startwtime = MPI_Wtime(); 39 | 40 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 41 | 42 | h = 1.0 / (double) n; 43 | sum = 0.0; 44 | /* A slightly better approach starts from large i and works back */ 45 | for (i = myid + 1; i <= n; i += numprocs) 46 | { 47 | x = h * ((double)i - 0.5); 48 | sum += f(x); 49 | } 50 | mypi = h * sum; 51 | 52 | MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); 53 | 54 | if (myid == 0) { 55 | endwtime = MPI_Wtime(); 56 | printf("pi is approximately %.16f, Error is %.16f\n", 57 | pi, fabs(pi - PI25DT)); 58 | printf("wall clock time = %f\n", endwtime-startwtime); 59 | fflush(stdout); 60 | } 61 | 62 | MPI_Finalize(); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 University of Maryland and other CallFlow Project Developers. 2 | # See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | # Minimal makefile for Sphinx documentation 7 | # 8 | 9 | # You can set these variables from the command line, and also 10 | # from the environment for the first two. 11 | SPHINXOPTS ?= 12 | SPHINXBUILD ?= sphinx-build 13 | SOURCEDIR = . 14 | BUILDDIR = _build 15 | 16 | # Put it first so that "make" without argument is like "make help". 17 | help: 18 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 19 | 20 | .PHONY: help Makefile 21 | 22 | # Catch-all target: route all unknown targets to Sphinx using the new 23 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 24 | %: Makefile 25 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 26 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 University of Maryland and other CallFlow Project Developers. 2 | # See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | # -*- coding: utf-8 -*- 7 | 8 | # Configuration file for the Sphinx documentation builder. 9 | # 10 | # This file only contains a selection of the most common options. For a full 11 | # list see the documentation: 12 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 13 | 14 | # -- Path setup -------------------------------------------------------------- 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | # import os 21 | import sys 22 | 23 | # sys.path.insert(0, os.path.abspath('.')) 24 | 25 | # The name of the Pygments (syntax highlighting) style to use. 26 | from pygments.styles.default import DefaultStyle 27 | from pygments.token import Generic 28 | 29 | import pkg_resources 30 | 31 | 32 | # -- Project information ----------------------------------------------------- 33 | 34 | project = "CallFlow" 35 | copyright = "2017-2020, Lawrence Livermore National Security, LLC" 36 | author = "Suraj P. Kesavan, Huu Tan Nguyen" 37 | 38 | # The full version, including alpha/beta/rc tags 39 | release = "1.1.0" 40 | 41 | 42 | # -- General configuration --------------------------------------------------- 43 | 44 | # Add any Sphinx extension module names here, as strings. They can be 45 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 46 | # ones. 47 | extensions = [ 48 | "sphinx.ext.autodoc", 49 | "sphinx.ext.todo", 50 | "sphinx.ext.imgmath", 51 | "sphinx.ext.viewcode", 52 | "sphinx.ext.githubpages", 53 | "sphinx.ext.napoleon", 54 | ] 55 | 56 | # Add any paths that contain templates here, relative to this directory. 57 | templates_path = ["_templates"] 58 | 59 | # List of patterns, relative to source directory, that match files and 60 | # directories to ignore when looking for source files. 61 | # This pattern also affects html_static_path and html_extra_path. 62 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 63 | 64 | 65 | # modifications to the default style 66 | class CallFlowStyle(DefaultStyle): 67 | styles = DefaultStyle.styles.copy() 68 | background_color = "#f4f4f8" 69 | styles[Generic.Output] = "#355" 70 | styles[Generic.Prompt] = "bold #346ec9" 71 | 72 | 73 | dist = pkg_resources.Distribution(__file__) 74 | sys.path.append(".") # make 'conf' module findable 75 | ep = pkg_resources.EntryPoint.parse("callflow = conf:CallFlowStyle", dist=dist) 76 | dist._ep_map = {"pygments.styles": {"plugin1": ep}} 77 | pkg_resources.working_set.add(dist) 78 | 79 | pygments_style = "callflow" 80 | 81 | # Sets the master_doc variable to avoid the issue (https://github.com/readthedocs/readthedocs.org/issues/2569) 82 | master_doc = "index" 83 | 84 | 85 | # -- Options for HTML output ------------------------------------------------- 86 | 87 | # The theme to use for HTML and HTML Help pages. See the documentation for 88 | # a list of builtin themes. 89 | # 90 | html_theme = "sphinx_rtd_theme" 91 | 92 | # Theme options are theme-specific and customize the look and feel of a theme 93 | # further. For a list of options available for each theme, see the 94 | # documentation. 95 | # 96 | html_theme_options = { 97 | "canonical_url": "", 98 | "analytics_id": "", 99 | "logo_only": True, 100 | "display_version": True, 101 | "prev_next_buttons_location": "bottom", 102 | "style_external_links": False, 103 | # Toc options 104 | "collapse_navigation": True, 105 | "sticky_navigation": True, 106 | "navigation_depth": 4, 107 | "includehidden": True, 108 | "titles_only": False, 109 | } 110 | 111 | # Add any paths that contain custom static files (such as style sheets) here, 112 | # relative to this directory. They are copied after the builtin static files, 113 | # so a file named "default.css" will overwrite the builtin "default.css". 114 | html_static_path = [""] 115 | -------------------------------------------------------------------------------- /docs/examples/callflow.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "experiment": "experiment_name", 3 | "save_path": "/path/to/dir", 4 | "read_parameter": false, 5 | "runs": [{ 6 | "name": "run-1", 7 | "path": "/path/to/run-1", 8 | "profile_format": "hpctoolkit | caliper | caliper_json" 9 | }, 10 | { 11 | "name": "run-2", 12 | "path": "/path/to/run-2", 13 | "profile_format": "hpctoolkit | caliper | caliper_json" 14 | }, 15 | { 16 | "name": "run-3", 17 | "path": "/path/to/run-3", 18 | "profile_format": "hpctoolkit | caliper | caliper_json" 19 | } 20 | ], 21 | "schema": { 22 | "filter_by": "time (inc)", 23 | "filter_perc": 0, 24 | "group_by": "name", 25 | "module_map": { 26 | "Lulesh": ["main", "lulesh.cycle"], 27 | "LeapFrog": ["LagrangeNodal", "LagrangeLeapFrog"], 28 | "CalcForce": ["CalcForceForNodes", "CalcVolumeForceForElems", "CalcHourglassControlForElems", "CalcFBHourglassForceForElems"], 29 | "CalcLagrange": ["LagrangeElements", "UpdateVolumesForElems", "CalcLagrangeElements", "CalcKinematicsForElems", "CalcQForElems", "CalcMonotonicQGradientsForElems", "CalcMonotonicQRegionForElems", "ApplyMaterialPropertiesForElems", "EvalEOSForElems", "CalcEnergyForElems", "CalcPressureForElems", "CalcSoundSpeedForElems", "IntegrateStressForElems"], 30 | "Timer": ["TimeIncrement"], 31 | "CalcConstraint": ["CalcTimeConstraintsForElems", "CalcCourantConstraintForElems", "CalcHydroConstraintForElems"], 32 | "NA": ["Unknown"], 33 | "MPI": ["MPI_Barrier", "MPI_Reduce", "MPI_Allreduce", "MPI_Irecv", "MPI_Isend", "MPI_Wait", "MPI_Waitall", "MPI_Finalize"] 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /docs/figures/CallFlow-basic-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/docs/figures/CallFlow-basic-architecture.png -------------------------------------------------------------------------------- /docs/getting_started.rst: -------------------------------------------------------------------------------- 1 | .. Copyright 2020 University of Maryland and other CallFlow Project Developers. 2 | See the top-level LICENSE file for details. 3 | 4 | SPDX-License-Identifier: MIT 5 | 6 | *************** 7 | Getting Started 8 | *************** 9 | 10 | Prerequisites 11 | ============= 12 | 13 | The callflow (python package) requires python (>= 3.6) and pip (>= 20.1.1). Other dependencies are checked/installed during the installation of callflow using pip. 14 | 15 | Other dependencies are: 16 | 17 | #. hatchet 18 | #. pandas 19 | #. networkx (2.2) 20 | #. numpy 21 | #. flask 22 | #. statsmodels, and 23 | #. sklearn 24 | 25 | CallFlow is available on `GitHub `_ 26 | 27 | The callflow app (visualization component) requires node.js (>= 13.7.0) and npm (>= 6.13.7). If there is an older version of node installed, install nvm and use the following command to change version. 28 | 29 | .. code-block:: console 30 | 31 | $ nvm use 13.7.0. 32 | 33 | Installation 34 | ============ 35 | 36 | You can get CallFlow from its `GitHub `_ using this command: 37 | 38 | .. code-block:: console 39 | 40 | $ git clone https://github.com/LLNL/CallFlow.git 41 | 42 | Install callflow python package 43 | ------------------------------- 44 | To install callflow python package, run the following command using `setup.py`. 45 | 46 | .. code-block:: console 47 | 48 | $ python3 setup.py install 49 | 50 | To install in the dev mode, 51 | 52 | .. code-block:: console 53 | 54 | $ pip install -e . --prefix=/path/to/install 55 | 56 | Check Installation of callflow python package 57 | --------------------------------------------- 58 | After installing callflow, make sure you update your PYTHONPATH environment variable to point to directory where callflow was installed. 59 | 60 | .. code-block:: console 61 | 62 | $ python 63 | Python 3.7.7 (default, Jul 11 2019, 01:08:00) 64 | [Clang 11.0.0 (clang-1100.0.33.17)]] on darwin 65 | Type "help", "copyright", "credits" or "license" for more information. 66 | >>> 67 | 68 | Typing ``import callflow`` at the prompt should succeed without any error messages: 69 | 70 | .. code-block:: console 71 | 72 | >>> import callflow 73 | >>> 74 | 75 | Install the Visualization client 76 | -------------------------------- 77 | 78 | .. code-block:: console 79 | 80 | $ cd app 81 | $ npm install 82 | 83 | Supported data formats 84 | ====================== 85 | 86 | Currently, hatchet supports the following data formats as input: 87 | 88 | * `HPCToolkit `_ database: This is generated 89 | by using ``hpcprof-mpi`` to post-process the raw measurements directory 90 | output by HPCToolkit. 91 | * Caliper `Cali `_ file: 92 | This is the format in which caliper outputs raw performance data by default. 93 | * Caliper `Json-split 94 | `_ file: This is 95 | generated by either running cali-query on the raw caliper data or by enabling 96 | the mpireport service when using caliper. 97 | 98 | For more details on the different input file formats, refer to the 99 | :doc:`User Guide `. 100 | 101 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Copyright 2020 University of Maryland and other CallFlow Project Developers. 2 | See the top-level LICENSE file for details. 3 | 4 | SPDX-License-Identifier: MIT 5 | 6 | .. CallFlow documentation master file, created by 7 | sphinx-quickstart on Mon Jul 27 16:48:43 2020. 8 | You can adapt this file completely to your liking, but it should at least 9 | contain the root `toctree` directive. 10 | 11 | ######## 12 | CallFlow 13 | ######## 14 | 15 | CallFlow is an interactive visual analysis tool that provides a high-level 16 | overview of CCTs together with semantic refinement operations to progressively explore the CCTs. 17 | 18 | You can get CallFlow from its `GitHub repository 19 | `_: 20 | 21 | .. code-block:: console 22 | 23 | $ git clone https://github.com/LLNL/CallFlow.git 24 | 25 | If you are new to CallFlow and want to start using it, see :doc:`Getting Started 26 | `, or refer to the full :doc:`User Guide ` below. 27 | 28 | 29 | .. toctree:: 30 | :maxdepth: 2 31 | :caption: User Docs 32 | 33 | getting_started 34 | user_guide 35 | 36 | 37 | If you encounter bugs while using CallFlow, you can report them by opening an 38 | issue on `GitHub `_. 39 | 40 | If you are referencing CallFlow in a publication, please cite the 41 | following `paper `_: 42 | 43 | * Huu Tan Nguyen, Abhinav Bhatele, Nikhil Jain, Suraj Kesavan, Harsh Bhatia, 44 | Todd Gamblin, Kwan-Liu Ma, and Peer-Timo Bremer. Visualizing Hierarchical 45 | Performance Profiles of Parallel Codes using CallFlow. In IEEE Transactions 46 | on Visualization and Computer Graphics, November 2019. 47 | `DOI `_ 48 | 49 | 50 | ################## 51 | Indices and tables 52 | ################## 53 | 54 | * :ref:`genindex` 55 | * :ref:`modindex` 56 | * :ref:`search` 57 | -------------------------------------------------------------------------------- /examples/%callflow-ipython-magic.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import callflow" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 2, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "%load_ext callflow" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 3, 24 | "metadata": { 25 | "scrolled": true 26 | }, 27 | "outputs": [ 28 | { 29 | "data": { 30 | "text/plain": [ 31 | "Reusing CallFlow's server is on port 5000 and client is on 1024 (pid 7827), started 0:19:01 ago. (Use '!kill 7827' to kill it.)" 32 | ] 33 | }, 34 | "metadata": {}, 35 | "output_type": "display_data" 36 | }, 37 | { 38 | "data": { 39 | "text/html": [ 40 | "\n", 41 | " \n", 43 | " \n", 54 | " " 55 | ], 56 | "text/plain": [ 57 | "" 58 | ] 59 | }, 60 | "metadata": {}, 61 | "output_type": "display_data" 62 | } 63 | ], 64 | "source": [ 65 | "%callflow --data_dir /Users/jarus/Work/llnl/CallFlow/data/lulesh-8-runs --profile_format caliper_json" 66 | ] 67 | } 68 | ], 69 | "metadata": { 70 | "kernelspec": { 71 | "display_name": "Python 3", 72 | "language": "python", 73 | "name": "python3" 74 | }, 75 | "language_info": { 76 | "codemirror_mode": { 77 | "name": "ipython", 78 | "version": 3 79 | }, 80 | "file_extension": ".py", 81 | "mimetype": "text/x-python", 82 | "name": "python", 83 | "nbconvert_exporter": "python", 84 | "pygments_lexer": "ipython3", 85 | "version": "3.8.5" 86 | } 87 | }, 88 | "nbformat": 4, 89 | "nbformat_minor": 2 90 | } 91 | -------------------------------------------------------------------------------- /experiments/cycle_issue: -------------------------------------------------------------------------------- 1 | {'callsite': '', 'module': 'libmonitor.so.0.0.0', 'level': 0, 'type': 'super-node'}, 2 | {'callsite': 'main', 'module': 'cpi', 'level': 1, 'type': 'super-node'} 3 | 4 | 5 | {'callsite': 'main', 'module': 'cpi', 'level': 1, 'type': 'super-node'}, 6 | {'callsite': '62:MPI_Finalize', 'module': 'libmonitor.so.0.0.0', 'level': 2, 'type': 'component-node'} 7 | 8 | 9 | {'callsite': '62:MPI_Finalize', 'module': 'libmonitor.so.0.0.0', 'level': 2, 'type': 'component-node'}, 10 | {'callsite': 'PMPI_Finalize', 'module': 'libmpi.so.12.0.5', 'level': 3, 'type': 'super-node'} 11 | 12 | 13 | {'callsite': 'main', 'module': 'cpi', 'level': 1, 'type': 'super-node'}, 14 | {'callsite': '27:MPI_Init', 'module': 'libmonitor.so.0.0.0', 'level': 2, 'type': 'component-node'} 15 | 16 | 17 | {'callsite': '27:MPI_Init', 'module': 'libmonitor.so.0.0.0', 'level': 2, 'type': 'component-node'}, 18 | {'callsite': 'PMPI_Init', 'module': 'libmpi.so.12.0.5', 'level': 3, 'type': 'super-node'} 19 | 20 | 21 | {'callsite': 'PMPI_Init', 'module': 'libmpi.so.12.0.5', 'level': 3, 'type': 'super-node'}, 22 | {'callsite': '348:', 'module': 'libpsm_infinipath.so.1.14', 'level': 4, 'type': 'super-node'} 23 | 24 | 25 | {'callsite': '36:', 'module': 'libpsm_infinipath.so.1.14', 'level': 4, 'type': 'super-node'}, 26 | {'callsite': ':0', 'module': 'Unknown', 'level': 5, 'type': 'super-node'} 27 | 28 | 29 | {'callsite': '36:', 'module': 'libpsm_infinipath.so.1.14', 'level': 4, 'type': 'super-node'}, 30 | {'callsite': '__GI_sched_yield', 'module': 'libc-2.12.so', 'level': 5, 'type': 'super-node'} 31 | 32 | 33 | {'callsite': '__GI_sched_yield', 'module': 'libc-2.12.so', 'level': 5, 'type': 'super-node'}, 34 | {'callsite': 'interp.c:0', 'module': 'Unknown', 'level': 6, 'type': 'super-node'} 35 | 36 | 37 | {'callsite': '348:', 'module': 'libpsm_infinipath.so.1.14', 'level': 4, 'type': 'super-node'}, 38 | {'callsite': 'pthread_create', 'module': 'libmonitor.so.0.0.0', 'level': 5, 'type': 'component-node'} -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0"] 3 | build-backend = "setuptools.build_meta" -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = --durations=20 -ra 3 | testpaths = callflow/tests 4 | python_files = *.py -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | colorlog==4.1.0 2 | llnl-hatchet 3 | matplotlib==3.1.1 4 | jsonschema==3.0.2 5 | networkx==2.5 6 | scipy==1.3.1 7 | numpy==1.17.2 8 | pandas==1.2.2 9 | ipython==7.18.1 10 | scikit_learn==0.23.2 11 | Flask-Cors==3.0.10 12 | psutil==5.8.0 13 | -------------------------------------------------------------------------------- /server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LLNL/CallFlow/6bbdabe4b71be369e616e3136d7f0120531c9fc8/server/__init__.py -------------------------------------------------------------------------------- /server/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2021 Lawrence Livermore National Security, LLC and other 2 | # CallFlow Project Developers. See the top-level LICENSE file for details. 3 | # 4 | # SPDX-License-Identifier: MIT 5 | 6 | # ------------------------------------------------------------------------------ 7 | # General imports. 8 | import os 9 | import sys 10 | 11 | # ------------------------------------------------------------------------------ 12 | # CallFlow local imports. 13 | import callflow 14 | from callflow.utils.argparser import ArgParser 15 | 16 | from .provider_base import BaseProvider 17 | from .provider_api import APIProvider 18 | from .notebook_server import launch_ipython 19 | from callflow.operations import Config 20 | 21 | LOGGER = callflow.get_logger(__name__) 22 | 23 | CALLFLOW_APP_HOST = os.getenv("CALLFLOW_APP_HOST", "127.0.0.1") 24 | CALLFLOW_APP_PORT = int(os.getenv("CALLFLOW_APP_PORT", 5000)) 25 | 26 | 27 | # ------------------------------------------------------------------------------ 28 | def main(): 29 | """ 30 | Main function triggered by the `callflow` interface. 31 | Performs actions depending on the passed arguments 32 | :return: None 33 | """ 34 | # -------------------------------------------------------------------------- 35 | # scan the args for log file and log level 36 | nargs = len(sys.argv) 37 | log_file = "" 38 | for i in range(1, nargs): 39 | if sys.argv[i] != "--log": 40 | continue 41 | if i == nargs - 1: 42 | raise ValueError("Please provide a filename to go with --log option") 43 | log_file = sys.argv[i + 1] 44 | if log_file.startswith("--"): 45 | raise ValueError("Please provide a valid filename to go with --log option") 46 | break 47 | 48 | log_level = 1 if "--verbose" in sys.argv else 2 49 | mem_usage = "--verbose" in sys.argv # show mem usage in verbose mode 50 | callflow.init_logger(level=log_level, file=log_file, mem_usage=mem_usage) 51 | 52 | # -------------------------------------------------------------------------- 53 | LOGGER.info(f" ------- Initializing CallFlow {callflow.__version__} --------") 54 | 55 | # -------------------------------------------------------------------------- 56 | args = ArgParser(sys.argv) 57 | debug = args.args["verbose"] # noqa 58 | production = args.args["production"] # noqa 59 | process = args.args["process"] 60 | endpoint_access = args.args.get("endpoint_access", "REST") 61 | endpoint_env = args.args.get("endpoint_env", "TERMINAL") 62 | reset = args.args["reset"] 63 | 64 | assert endpoint_env in ["TERMINAL", "JUPYTER"] 65 | 66 | # Get config object. 67 | config = Config(args.args).get_config() 68 | 69 | # -------------------------------------------------------------------------- 70 | # process and exit 71 | if process: 72 | assert endpoint_env == "TERMINAL" 73 | cf = BaseProvider(config=config) 74 | cf.process(reset) 75 | 76 | # -------------------------------------------------------------------------- 77 | # start a server based on endpoint_access = "REST" 78 | elif not process and endpoint_env == "TERMINAL": 79 | cf = APIProvider(config=config) 80 | cf.load() 81 | cf.start(host=CALLFLOW_APP_HOST, port=CALLFLOW_APP_PORT) 82 | 83 | # -------------------------------------------------------------------------- 84 | # launch an ipython instance 85 | elif not process and endpoint_env == "JUPYTER": 86 | _launch_path = os.path.join(config["save_path"], "launch-info") 87 | launch_ipython( 88 | args.args, 89 | config, 90 | host=CALLFLOW_APP_HOST, 91 | port=CALLFLOW_APP_PORT, 92 | launch_path=_launch_path, 93 | app_version=callflow.__version__, 94 | ) 95 | 96 | # -------------------------------------------------------------------------- 97 | # Invalid options 98 | else: 99 | s = ( 100 | f"Invalid options " 101 | f"(process={process}, access={endpoint_access}, env={endpoint_env})" 102 | ) 103 | raise Exception(s) 104 | 105 | # -------------------------------------------------------------------------- 106 | 107 | 108 | # -------------------------------------------------------------------------- 109 | if __name__ == "__main__": 110 | main() 111 | 112 | # ------------------------------------------------------------------------------ 113 | --------------------------------------------------------------------------------