├── oasys
├── tests
│ ├── __init__.py
│ └── test_addons.py
├── util
│ ├── __init__.py
│ ├── script
│ │ ├── __init__.py
│ │ └── value.py
│ ├── oasys_objects.py
│ ├── oasys_registry.py
│ ├── custom_distribution.py
│ └── external_command.py
├── application
│ ├── __init__.py
│ └── data
│ │ ├── INTERNAL_LIBRARIES_PY37.txt
│ │ ├── OFFICIAL_ADDONS.txt
│ │ └── INTERNAL_LIBRARIES_PY38.txt
├── widgets
│ ├── abstract
│ │ ├── __init__.py
│ │ └── scanning
│ │ │ ├── __init__.py
│ │ │ ├── abstract_scan_file_node_point.py
│ │ │ └── abstract_scan_variable_node_point.py
│ ├── __init__.py
│ ├── tools
│ │ ├── icons
│ │ │ ├── hdf5.png
│ │ │ ├── tools.png
│ │ │ ├── github.png
│ │ │ ├── histogram.png
│ │ │ ├── python_script.png
│ │ │ ├── surface_merger.png
│ │ │ └── surface_reader.png
│ │ ├── __init__.py
│ │ ├── ow_hdf5_file_reader.py
│ │ ├── ow_surface_file_reader.py
│ │ └── ow_surface_file_merger.py
│ ├── loop_management
│ │ ├── icons
│ │ │ ├── pin.png
│ │ │ ├── cycle.png
│ │ │ └── loop_management.png
│ │ ├── __init__.py
│ │ ├── ow_pin.py
│ │ └── ow_node_point.py
│ ├── scanning
│ │ ├── icons
│ │ │ ├── cycle_file.png
│ │ │ ├── scanning.png
│ │ │ └── cycle_variable.png
│ │ ├── __init__.py
│ │ ├── ow_scan_file_node_point.py
│ │ └── ow_scan_variable_node_point.py
│ ├── exchange.py
│ ├── congruence.py
│ └── widget.py
├── menus
│ ├── __init__.py
│ └── menu.py
├── canvas
│ ├── styles
│ │ ├── __init__.py
│ │ ├── orange
│ │ │ ├── Dropdown.svg
│ │ │ ├── Pause.svg
│ │ │ ├── Arrow.svg
│ │ │ ├── Text Size.svg
│ │ │ ├── Document Info.svg
│ │ │ ├── Search.svg
│ │ │ ├── Grid.svg
│ │ │ └── Info.svg
│ │ └── orange.qss
│ ├── icons
│ │ ├── doc.png
│ │ ├── error.png
│ │ ├── exit.png
│ │ ├── frame.png
│ │ ├── oasys.png
│ │ ├── open.png
│ │ ├── print.png
│ │ ├── save.png
│ │ ├── text.png
│ │ ├── delete.png
│ │ ├── folders.png
│ │ ├── frame2.png
│ │ ├── options.png
│ │ ├── orange.icns
│ │ ├── output.png
│ │ ├── splash.png
│ │ ├── update.png
│ │ ├── update1.png
│ │ ├── warning.png
│ │ ├── categories.png
│ │ ├── folders2.png
│ │ ├── leftEdge.png
│ │ ├── leftEdgeG.png
│ │ ├── leftEdgeR.png
│ │ ├── moveleft.png
│ │ ├── moveright.png
│ │ ├── rightEdge.png
│ │ ├── rightEdgeG.png
│ │ ├── rightEdgeR.png
│ │ ├── application.png
│ │ ├── delete_gray.png
│ │ ├── information.png
│ │ ├── triangle-red.png
│ │ ├── triangle-blue.png
│ │ ├── triangle-orange.png
│ │ ├── oasys-splash-screen.png
│ │ ├── arrow-right.svg
│ │ ├── Dropdown.svg
│ │ ├── Arrow.svg
│ │ ├── Pause.svg
│ │ ├── Maximize Toolbar.svg
│ │ ├── Minimize Toolbar.svg
│ │ ├── Back.svg
│ │ ├── Install.svg
│ │ ├── default-category.svg
│ │ ├── Text Size.svg
│ │ ├── default-widget.svg
│ │ ├── New.svg
│ │ ├── Recent.svg
│ │ ├── Document Info.svg
│ │ ├── Search.svg
│ │ ├── Update.svg
│ │ ├── Grid.svg
│ │ ├── Tutorials.svg
│ │ ├── Info.svg
│ │ ├── Open.svg
│ │ ├── Documentation.svg
│ │ └── orange-canvas.svg
│ ├── __init__.py
│ ├── discovery.py
│ ├── conf.py
│ └── widgetsscheme.py
└── __init__.py
├── scripts
└── macos
│ ├── skeleton.app
│ └── Contents
│ │ ├── PkgInfo
│ │ ├── Resources
│ │ ├── oasys1.icns
│ │ └── schema.icns
│ │ ├── Frameworks
│ │ ├── lib
│ │ │ ├── libxrl.7.dylib
│ │ │ ├── libgcc_s.1.dylib
│ │ │ ├── libxrlf03.7.dylib
│ │ │ ├── libgfortran.3.dylib
│ │ │ └── libquadmath.0.dylib
│ │ └── xraylib
│ │ │ ├── _xraylib.la
│ │ │ ├── xraylib_np.la
│ │ │ ├── xrayhelp.py
│ │ │ └── xraymessages.py
│ │ ├── MacOS
│ │ └── ENV
│ │ └── Info.plist.in
│ ├── dmg-resources
│ ├── DS_Store
│ ├── VolumeIcon.icns
│ ├── background.png
│ ├── wonder_volume.icns
│ └── README.txt
│ ├── requirements.txt
│ ├── README.txt
│ ├── sign-app.sh
│ ├── sign-dmg.sh
│ ├── create-dmg-installer.sh
│ ├── build-macos-app.sh
│ └── python-framework.sh
├── .travis.yml
├── .gitignore
├── MANIFEST.in
├── README.md
├── .gitattributes
└── setup.py
/oasys/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oasys/util/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oasys/application/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oasys/util/script/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oasys/widgets/abstract/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oasys/widgets/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | """
3 |
--------------------------------------------------------------------------------
/oasys/widgets/abstract/scanning/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oasys/menus/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'labx'
2 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/PkgInfo:
--------------------------------------------------------------------------------
1 | APPLOrng
--------------------------------------------------------------------------------
/oasys/canvas/styles/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | QSS style sheets.
3 |
4 | """
5 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/doc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/doc.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/error.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/exit.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/frame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/frame.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/oasys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/oasys.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/open.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/print.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/print.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/save.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/text.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/delete.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/folders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/folders.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/frame2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/frame2.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/options.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/orange.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/orange.icns
--------------------------------------------------------------------------------
/oasys/canvas/icons/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/output.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/splash.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/update.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/update1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/update1.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/warning.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/categories.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/categories.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/folders2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/folders2.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/leftEdge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/leftEdge.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/leftEdgeG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/leftEdgeG.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/leftEdgeR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/leftEdgeR.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/moveleft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/moveleft.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/moveright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/moveright.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/rightEdge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/rightEdge.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/rightEdgeG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/rightEdgeG.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/rightEdgeR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/rightEdgeR.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/application.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/delete_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/delete_gray.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/information.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/information.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/triangle-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/triangle-red.png
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/hdf5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/hdf5.png
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/tools.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/triangle-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/triangle-blue.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/triangle-orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/triangle-orange.png
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/github.png
--------------------------------------------------------------------------------
/scripts/macos/dmg-resources/DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/dmg-resources/DS_Store
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/histogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/histogram.png
--------------------------------------------------------------------------------
/oasys/canvas/icons/oasys-splash-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/canvas/icons/oasys-splash-screen.png
--------------------------------------------------------------------------------
/oasys/widgets/loop_management/icons/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/loop_management/icons/pin.png
--------------------------------------------------------------------------------
/oasys/widgets/scanning/icons/cycle_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/scanning/icons/cycle_file.png
--------------------------------------------------------------------------------
/oasys/widgets/scanning/icons/scanning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/scanning/icons/scanning.png
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/python_script.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/python_script.png
--------------------------------------------------------------------------------
/scripts/macos/dmg-resources/VolumeIcon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/dmg-resources/VolumeIcon.icns
--------------------------------------------------------------------------------
/scripts/macos/dmg-resources/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/dmg-resources/background.png
--------------------------------------------------------------------------------
/oasys/widgets/loop_management/icons/cycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/loop_management/icons/cycle.png
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/surface_merger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/surface_merger.png
--------------------------------------------------------------------------------
/oasys/widgets/tools/icons/surface_reader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/tools/icons/surface_reader.png
--------------------------------------------------------------------------------
/oasys/widgets/scanning/icons/cycle_variable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/scanning/icons/cycle_variable.png
--------------------------------------------------------------------------------
/scripts/macos/dmg-resources/wonder_volume.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/dmg-resources/wonder_volume.icns
--------------------------------------------------------------------------------
/oasys/widgets/loop_management/icons/loop_management.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/oasys/widgets/loop_management/icons/loop_management.png
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Resources/oasys1.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Resources/oasys1.icns
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Resources/schema.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Resources/schema.icns
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/lib/libxrl.7.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Frameworks/lib/libxrl.7.dylib
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | dist: xenial
2 | language: python
3 | python:
4 | - 3.5
5 | - 3.6
6 | - 3.7
7 |
8 | install:
9 | - pip install .
10 |
11 | script:
12 | pytest oasys/tests
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/lib/libgcc_s.1.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Frameworks/lib/libgcc_s.1.dylib
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/lib/libxrlf03.7.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Frameworks/lib/libxrlf03.7.dylib
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/lib/libgfortran.3.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Frameworks/lib/libgfortran.3.dylib
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/lib/libquadmath.0.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oasys-kit/OASYS1/HEAD/scripts/macos/skeleton.app/Contents/Frameworks/lib/libquadmath.0.dylib
--------------------------------------------------------------------------------
/oasys/application/data/INTERNAL_LIBRARIES_PY37.txt:
--------------------------------------------------------------------------------
1 | numpy==1.21.6
2 | fabio==0.11.0
3 | scipy==1.7.3
4 | srxraylib
5 | syned
6 | wofry
7 | OASYS1
8 | silx==0.15.0
9 | PyQt5==5.15.2
10 | pip==22.2.2
11 |
--------------------------------------------------------------------------------
/oasys/application/data/OFFICIAL_ADDONS.txt:
--------------------------------------------------------------------------------
1 | OASYS1-ShadowOui
2 | OASYS1-ShadowOui-Advanced-Tools
3 | OASYS1-SHADOW4
4 | OASYS1-SHADOW4-Advanced
5 | OASYS1-SRW
6 | OASYS1-XOPPY
7 | OASYS1-XRayServer
8 | OASYS1-SYNED
9 | OASYS1-WOFRY
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build files
2 | build
3 | dist
4 | *.egg-info
5 | MANIFEST
6 | oasys/version.py
7 | doc/build
8 | ENV/
9 |
10 | *.so
11 | *.pyd
12 | *.pyc
13 |
14 | __pycache__
15 |
16 | # Hidden files
17 | .*
18 |
19 | # Editor files
20 | *~
21 |
22 |
--------------------------------------------------------------------------------
/oasys/application/data/INTERNAL_LIBRARIES_PY38.txt:
--------------------------------------------------------------------------------
1 | numpy==1.22.4
2 | fabio==0.11.0
3 | scipy==1.9.1
4 | srxraylib
5 | syned
6 | syned-gui
7 | wofry
8 | wofryimpl
9 | shadow-hybrid-methods
10 | OASYS1
11 | silx==0.15.0
12 | PyQt5==5.15.2
13 | pip==23.3.1
14 |
15 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include oasys *.py
2 | recursive-include oasys/canvas/styles *.qss
3 | recursive-include oasys/canvas *.png *.svg *.ico
4 | recursive-include oasys/application/data *.txt
5 |
6 | recursive-include oasys/widgets *.png *.svg
7 |
8 | include LICENSE
9 |
--------------------------------------------------------------------------------
/oasys/__init__.py:
--------------------------------------------------------------------------------
1 | try:
2 | from .import version
3 | # Always use short_version here (see PEP 386)
4 | __version__ = version.short_version
5 | __git_revision__ = version.git_revision
6 | except ImportError:
7 | __version__ = "unknown"
8 | __git_revision__ = "unknown"
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OASYS 1.3
2 | OASYS (OrAnge SYnchrotron Suite) is a graphical environment
3 | for optic simulation software used in synchrotron facilities,
4 | based on Orange 3.
5 |
6 | OASYS package requires Python 3.8 or newer.
7 |
8 | Instructions to install OASYS are here: https://github.com/oasys-kit/oasys-installation-scripts/wiki
9 |
--------------------------------------------------------------------------------
/scripts/macos/requirements.txt:
--------------------------------------------------------------------------------
1 | # Fixed requirements file for creating a python environment for
2 | # macOS Orange.app.
3 |
4 | # Prebuild dependencies that themself do not publish wheels (e.g. bottleneck)
5 | --find-links=https://orange.biolab.si/download/files/wheelhouse
6 |
7 | requests
8 | numpy
9 | scipy
10 | matplotlib>=3.0.3
11 | pyqt5>=5.12
12 | pyqtwebengine
13 |
--------------------------------------------------------------------------------
/oasys/widgets/tools/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'labx'
2 |
3 | """
4 | =========
5 | Tools
6 | =========
7 |
8 | Widgets for common tools.
9 |
10 | """
11 |
12 | # Category description for the widget registry
13 |
14 | NAME = "Tools"
15 |
16 | DESCRIPTION = "Widgets for Common Tools."
17 |
18 | BACKGROUND = "#FAAC58"
19 |
20 | ICON = "icons/tools.png"
21 |
22 | PRIORITY = 1
23 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behaviour, in case users don't have core.autocrlf set.
2 | * text=auto
3 |
4 | # Explicitly declare text files we want to always be normalized and converted
5 | # to native line endings on checkout.
6 | *.py text
7 | *.pyx text
8 |
9 | # Denote all files that are truly binary and should not be modified.
10 | *.png binary
11 | *.jpg binary
12 | *.svg binary
13 |
--------------------------------------------------------------------------------
/oasys/canvas/__init__.py:
--------------------------------------------------------------------------------
1 | # pkg_resources selects a suitable resource loader based on the modules's
2 | # __loader__ attribute. In python2 it defaults to None, which maps to the
3 | # default resource loader, but it python3 it does not. As a result,
4 | # pkg_resources is unable to select a resource loader and load resources.
5 | # By settings __loader__ to None, we workaround the pkg_resources bug.
6 | __loader__ = None
7 |
--------------------------------------------------------------------------------
/oasys/widgets/loop_management/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'labx'
2 |
3 | """
4 | =========
5 | Loop Management
6 | =========
7 |
8 | Widgets for loop management
9 |
10 | """
11 |
12 | # Category description for the widget registry
13 |
14 | NAME = "Basic Loops"
15 |
16 | DESCRIPTION = "Widgets for Loop Management."
17 |
18 | BACKGROUND = "#FAAC58"
19 |
20 | ICON = "icons/loop_management.png"
21 |
22 | PRIORITY = 2
23 |
--------------------------------------------------------------------------------
/oasys/widgets/scanning/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'labx'
2 |
3 | """
4 | =========
5 | Scanning Loop Management
6 | =========
7 |
8 | Widgets for loop management
9 |
10 | """
11 |
12 | # Category description for the widget registry
13 |
14 | NAME = "Scanning Loops"
15 |
16 | DESCRIPTION = "Widgets for Loop Management."
17 |
18 | BACKGROUND = "#FAAC58"
19 |
20 | ICON = "icons/scanning.png"
21 |
22 | PRIORITY = 2.1
23 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/arrow-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/scripts/macos/README.txt:
--------------------------------------------------------------------------------
1 | Orange macOS application (.app) build scripts
2 | ---------------------------------------------
3 |
4 | Contents:
5 |
6 | python-framework.sh
7 | Download, unpack and make relocatable the official python.org framework
8 | installers (used by build-macos-app.sh)
9 |
10 | build-macos-app.sh
11 | Build an Orange.app application bundle from scratch
12 |
13 | create-dmg-installer.sh
14 | Pack the Orange.app applicaiton into a .dmg installer disk image
15 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Dropdown.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Dropdown.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Maximize Toolbar.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Minimize Toolbar.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Back.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/MacOS/ENV:
--------------------------------------------------------------------------------
1 | # Create an environment for running python from the bundle
2 | # Should be run as "source ENV"
3 |
4 | BUNDLE_DIR=`dirname "$0"`/../
5 | BUNDLE_DIR=`perl -MCwd=realpath -e 'print realpath($ARGV[0])' "$BUNDLE_DIR"`/
6 | FRAMEWORKS_DIR="$BUNDLE_DIR"Frameworks/
7 | RESOURCES_DIR="$BUNDLE_DIR"Resources/
8 |
9 | PYVERSION=“3.7”
10 | PYTHONEXECUTABLE="$FRAMEWORKS_DIR"Python.framework/Resources/Python.app/Contents/MacOS/Python
11 | PYTHONHOME="$FRAMEWORKS_DIR"Python.framework/Versions/"$PYVERSION"/
12 | DYLD_FRAMEWORK_PATH="$FRAMEWORKS_DIR"${DYLD_FRAMEWORK_PATH:+:$DYLD_FRAMEWORK_PATH}
13 |
14 | export PYTHONNOUSERSITE=1
15 |
16 | # Some non framework libraries are put in $FRAMEWORKS_DIR by machlib standalone
17 | export DYLD_LIBRARY_PATH="$FRAMEWORKS_DIR"${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}lib
18 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Install.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/oasys/tests/test_addons.py:
--------------------------------------------------------------------------------
1 | from unittest.mock import Mock
2 | import pytest
3 | from oasys.application.addons import is_updatable, Available, Installed, Installable
4 |
5 |
6 | @pytest.mark.parametrize('items,expected', [
7 | (Available(installable=True), False),
8 | (Installed(installable=None, local=Mock()), False),
9 | (Installed(installable=Installable(name='mock_name',
10 | version='2.0.0',
11 | summary='mock_summary',
12 | description='mock_description',
13 | package_url='mock_package_url',
14 | release_urls='mock_release_urls'),
15 | local=Mock(version='1.0.0')), True),
16 | ])
17 | def test_is_updatable(items, expected):
18 | assert is_updatable(items) == expected
19 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/default-category.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Text Size.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Text Size.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/default-widget.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/New.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Recent.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Document Info.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Document Info.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/xraylib/_xraylib.la:
--------------------------------------------------------------------------------
1 | # _xraylib.la - a libtool library file
2 | # Generated by libtool (GNU libtool) 2.4.6
3 | #
4 | # Please DO NOT delete this file!
5 | # It is necessary for linking the library.
6 |
7 | # The name that we can dlopen(3).
8 | dlname='_xraylib.cpython-37m-darwin.so'
9 |
10 | # Names of this library.
11 | library_names='_xraylib.cpython-37m-darwin.so _xraylib.cpython-37m-darwin.so'
12 |
13 | # The name of the static archive.
14 | old_library=''
15 |
16 | # Linker flags that cannot go in dependency_libs.
17 | inherited_linker_flags=' '
18 |
19 | # Libraries that this one depends upon.
20 | dependency_libs=' /usr/local/lib/libxrl.la -lm'
21 |
22 | # Names of additional weak libraries provided by this library
23 | weak_library_names=''
24 |
25 | # Version information for _xraylib.
26 | current=0
27 | age=0
28 | revision=0
29 |
30 | # Is this an already installed library?
31 | installed=yes
32 |
33 | # Should we warn about portability when linking against -modules?
34 | shouldnotlink=yes
35 |
36 | # Files to dlopen/dlpreopen
37 | dlopen=''
38 | dlpreopen=''
39 |
40 | # Directory that this library needs to be installed in:
41 | libdir='/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages'
42 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/xraylib/xraylib_np.la:
--------------------------------------------------------------------------------
1 | # xraylib_np.la - a libtool library file
2 | # Generated by libtool (GNU libtool) 2.4.6
3 | #
4 | # Please DO NOT delete this file!
5 | # It is necessary for linking the library.
6 |
7 | # The name that we can dlopen(3).
8 | dlname='xraylib_np.cpython-37m-darwin.so'
9 |
10 | # Names of this library.
11 | library_names='xraylib_np.cpython-37m-darwin.so xraylib_np.cpython-37m-darwin.so'
12 |
13 | # The name of the static archive.
14 | old_library=''
15 |
16 | # Linker flags that cannot go in dependency_libs.
17 | inherited_linker_flags=' '
18 |
19 | # Libraries that this one depends upon.
20 | dependency_libs=' /usr/local/lib/libxrl.la -lm'
21 |
22 | # Names of additional weak libraries provided by this library
23 | weak_library_names=''
24 |
25 | # Version information for xraylib_np.
26 | current=0
27 | age=0
28 | revision=0
29 |
30 | # Is this an already installed library?
31 | installed=yes
32 |
33 | # Should we warn about portability when linking against -modules?
34 | shouldnotlink=yes
35 |
36 | # Files to dlopen/dlpreopen
37 | dlopen=''
38 | dlpreopen=''
39 |
40 | # Directory that this library needs to be installed in:
41 | libdir='/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages'
42 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Search.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Update.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Search.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
--------------------------------------------------------------------------------
/oasys/widgets/loop_management/ow_pin.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from oasys.widgets import widget
4 |
5 | from orangewidget import gui
6 |
7 | from PyQt5 import QtGui
8 |
9 | from oasys.util.oasys_util import TriggerOut
10 |
11 | class Pin(widget.OWWidget):
12 |
13 | name = "Pin"
14 | description = "Tools: Pin"
15 | icon = "icons/pin.png"
16 | maintainer = "Luca Rebuffi"
17 | maintainer_email = "lrebuffi(@at@)anl.gov"
18 | priority = 3
19 | category = "User Defined"
20 | keywords = ["data", "file", "load", "read"]
21 |
22 | inputs = [("Trigger", TriggerOut, "passTrigger")]
23 |
24 | outputs = [{"name":"Trigger",
25 | "type":TriggerOut,
26 | "doc":"Trigger",
27 | "id":"Trigger"}]
28 |
29 | want_main_area = 0
30 | want_control_area = 1
31 |
32 | def __init__(self):
33 |
34 | self.setFixedWidth(300)
35 | self.setFixedHeight(100)
36 |
37 | gui.separator(self.controlArea, height=20)
38 | gui.label(self.controlArea, self, " SIMPLE PASSAGE POINT", orientation="horizontal")
39 | gui.rubber(self.controlArea)
40 |
41 | def passTrigger(self, trigger):
42 | self.send("Trigger", trigger)
43 |
44 | if __name__ == "__main__":
45 | a = QtGui.QApplication(sys.argv)
46 | ow = Pin()
47 | ow.show()
48 | a.exec_()
49 | ow.saveSettings()
50 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Grid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Tutorials.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
--------------------------------------------------------------------------------
/scripts/macos/sign-app.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | usage() {
6 | echo 'usage: sign-app.sh -s IDENTITY PATH
7 |
8 | Sign an Orange.app application at PATH and create a signed .dmg installer.
9 |
10 | OPTIONS
11 | --sign -s IDENTITY
12 | Signing identity to use. The \`identity\` must name a signing
13 | certificate in a macOS keychain (see \`man codesign\` SIGNING
14 | IDENTITIES section for details).
15 |
16 | --help -h
17 | Print this help.
18 | '
19 | }
20 |
21 | SCRIPTS=$( cd "$(dirname "$0")" ; pwd -P )
22 | DIST=$( cd "$(dirname "$0")/../../dist" ; pwd -P )
23 |
24 | IDENTITY="Developer ID"
25 |
26 | while true; do
27 | case "${1}" in
28 | -s|--sign) IDENTITY="${2:?"no identity provided"}"; shift 2;;
29 | -h|--help) usage; exit 0;;
30 | -*) echo "unrecognized parameter: ${1}" >&2; usage >&2; exit 1;;
31 | *) break;;
32 | esac
33 | done
34 |
35 | APPPATH=${1}
36 | if [ ! "${APPPATH}" ]; then
37 | APPPATH=${DIST}/Orange3.app
38 | echo "No path supplied; using default ${APPPATH}"
39 | fi
40 |
41 | VERSION=$(
42 | "${APPPATH}"/Contents/MacOS/python -c '
43 | import pkg_resources
44 | print(pkg_resources.get_distribution("Orange3").version)
45 | '
46 | )
47 |
48 | # Create disk image
49 | "${SCRIPTS}"/create-dmg-installer.sh --app "${APPPATH}" \
50 | --sign "${IDENTITY}" \
51 | "${DIST}/Orange3-${VERSION}.dmg"
52 |
53 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Grid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Info.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Open.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange/Info.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/oasys/widgets/exchange.py:
--------------------------------------------------------------------------------
1 | import numpy
2 |
3 | class DataExchangeObject(object):
4 | _content = None
5 |
6 | PROGRAM_NAME = "PROGRAM_NAME"
7 | WIDGET_NAME = "WIDGET_NAME"
8 |
9 | def __init__(self, program_name, widget_name):
10 | super().__init__()
11 |
12 | self._content = {DataExchangeObject.PROGRAM_NAME: program_name, DataExchangeObject.WIDGET_NAME: widget_name}
13 |
14 | def get_program_name(self):
15 | return self.get_content(DataExchangeObject.PROGRAM_NAME)
16 |
17 | def get_widget_name(self):
18 | return self.get_content(DataExchangeObject.WIDGET_NAME)
19 |
20 | def add_content(self, content_key="KEY", content_value=""):
21 | self._content[content_key] = content_value
22 |
23 | def get_content(self, content_key="KEY"):
24 | return self._content[content_key]
25 |
26 | def add_contents(self, content_keys=numpy.array(["KEY"]), content_values=numpy.array([""])):
27 | v_add_content = numpy.vectorize(self.add_content)
28 | v_add_content(content_keys, content_values)
29 |
30 | def get_contents(self, content_keys=numpy.array(["KEY"])):
31 | v_get_content = numpy.vectorize(self.get_content)
32 | return v_get_content(content_keys)
33 |
34 | def has_content_key(self, content_key):
35 | try:
36 | self._content[content_key]
37 | return True
38 | except:
39 | return False
40 |
41 | def content_keys(self):
42 | return self._content.keys()
43 |
--------------------------------------------------------------------------------
/oasys/canvas/discovery.py:
--------------------------------------------------------------------------------
1 | import pkgutil
2 | import inspect
3 | import logging
4 |
5 | from orangecanvas.registry import discovery
6 |
7 | from oasys.menus.menu import OMenu
8 |
9 | log = logging.getLogger(__name__)
10 |
11 |
12 | class MenuRegistry(object):
13 |
14 | def __init__(self, menus=None):
15 | self.registry = menus if menus is not None else []
16 |
17 | def menus(self):
18 | return self.registry
19 |
20 | def addMenu(self, menu):
21 | self.registry.append(menu)
22 |
23 |
24 | def omenus_from_package(package):
25 | try:
26 | package = discovery.asmodule(package)
27 | except ImportError:
28 | return
29 | for path in package.__path__:
30 | for _, mod_name, ispkg in pkgutil.iter_modules([path]):
31 | if ispkg:
32 | continue
33 |
34 | name = package.__name__ + "." + mod_name
35 | try:
36 | menu_module = discovery.asmodule(name)
37 | except ImportError:
38 | log.error("Error importing '%s'", name, exc_info=True)
39 | return
40 |
41 | for name, menu_class in inspect.getmembers(menu_module):
42 | if inspect.isclass(menu_class) and \
43 | issubclass(menu_class, OMenu) and not name == "OMenu":
44 | try:
45 | yield menu_class()
46 | except Exception:
47 | log.error("Error creating menu instance from '%s'",
48 | menu_class, exc_info=True)
49 |
--------------------------------------------------------------------------------
/oasys/util/oasys_objects.py:
--------------------------------------------------------------------------------
1 | class OasysSurfaceData(object):
2 | def __init__(self,
3 | xx=None,
4 | yy=None,
5 | zz=None,
6 | surface_data_file=None):
7 | self.xx = xx
8 | self.yy = yy
9 | self.zz = zz
10 | self.surface_data_file=surface_data_file
11 |
12 | class OasysErrorProfileData(object):
13 |
14 | def __init__(self,
15 | surface_data=None,
16 | error_profile_x_dim=0.0,
17 | error_profile_y_dim=0.0):
18 | self.surface_data = surface_data
19 | self.error_profile_x_dim = error_profile_x_dim
20 | self.error_profile_y_dim = error_profile_y_dim
21 |
22 | class OasysPreProcessorData(object):
23 |
24 | def __init__(self, error_profile_data=None, reflectivity_data=None):
25 | super().__init__()
26 |
27 | self.error_profile_data = error_profile_data
28 | self.reflectivity_data = reflectivity_data
29 | self.additional_data = None
30 |
31 | def set_additional_data(self, key, value):
32 | if self._additional_data is None:
33 | self._additional_data = {key : value}
34 | else:
35 | self._additional_data[key] = value
36 |
37 | def get_additional_data(self, key):
38 | return self._additional_data[key]
39 |
40 | def has_additional_data(self, key):
41 | return key in self._additional_data
42 |
43 | class OasysThicknessErrorsData(object):
44 | def __init__(self, thickness_error_profile_data_files=[]):
45 | self.thickness_error_profile_data_files = thickness_error_profile_data_files
46 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Info.plist.in:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleName
6 | Oasys1
7 | CFBundleExecutable
8 | Oasys1
9 | CFBundleIdentifier
10 | oasys1.anl.gov
11 | CFBundleGetInfoString
12 | OASYS (OrAnge SYnchrotron Suite)
13 | CFBundleVersion
14 | __VERSION__
15 | CFBundleShortVersionString
16 | __VERSION__
17 | CFBundleIconFile
18 | oasys1.icns
19 | CFBundlePackageType
20 | APPL
21 | CFBundleSignature
22 | Orng
23 | CFBundleDocumentTypes
24 |
25 |
26 | CFBundleTypeName
27 | OASYS Canvas Schema
28 | CFBundleTypeExtensions
29 |
30 | ows
31 |
32 | CFBundleTypeIconFile
33 | schema.icns
34 | CFBundleTypeRole
35 | Editor
36 | LSHandlerRank
37 | Default
38 |
39 |
40 | CFBundleInfoDictionaryVersion
41 | 6.0
42 | NSPrincipalClass
43 | NSApplication
44 | NSHighResolutionCapable
45 |
46 | LSMinimumSystemVersion
47 | 10.12.0
48 |
49 |
50 |
--------------------------------------------------------------------------------
/oasys/util/oasys_registry.py:
--------------------------------------------------------------------------------
1 | class AlreadyInitializedError(ValueError):
2 | def __init__(self, message=None): super(AlreadyInitializedError, self).__init__(message)
3 |
4 | class GenericRegistry(object):
5 | _NO_APPLICATION = ""
6 |
7 | def __init__(self, registry_name):
8 | self.__registry_name = registry_name
9 | self.__registry = {self._NO_APPLICATION: None}
10 |
11 | def register_instance(self, instance, application_name=None, replace=False):
12 | if instance is None: raise ValueError(self.__registry_name + " Instance is None")
13 |
14 | application_name = self.__get_application_name(application_name)
15 |
16 | if application_name in self.__registry.keys():
17 | if self.__registry[application_name] is None or replace==True: self.__registry[application_name] = instance
18 | else: raise AlreadyInitializedError(self.__registry_name + " Instance already initialized")
19 | else: self.__registry[application_name] = instance
20 |
21 | def reset(self, application_name=None):
22 | application_name = self.__get_application_name(application_name)
23 |
24 | if application_name in self.__registry.keys(): self.__registry[self.__get_application_name(application_name)] = None
25 | else: raise ValueError(self.__registry_name + " Instance not existing")
26 |
27 | def get_instance(self, application_name=None):
28 | application_name = self.__get_application_name(application_name)
29 |
30 | if application_name in self.__registry.keys(): return self.__registry[self.__get_application_name(application_name)]
31 | else: raise ValueError(self.__registry_name + " Instance not existing")
32 |
33 | def __get_application_name(self, application_name):
34 | return self._NO_APPLICATION if application_name is None else application_name
35 |
--------------------------------------------------------------------------------
/scripts/macos/dmg-resources/README.txt:
--------------------------------------------------------------------------------
1 | OSX dmg installer resources
2 | ===========================
3 |
4 | This directory contains the binary resources to create an
5 | Orange dmg installer.
6 |
7 |
8 | DS_Store
9 | OSX Desktop Services folder settings.
10 | Defined the folder background selection, icon positions and size,
11 | Finder window position and size, ...
12 | This gets copied to DMGROOT/.DS_Store
13 |
14 | VolumeIcon.icns
15 | Volume icon.
16 | This gets copied to DMGROOT/.VolumeIcon.icns
17 |
18 | background.png
19 | The background folder image.
20 | This gets copied to DMGROOT/.background/background.png
21 | as specified by DS_Store.
22 | Note if you change the path of the background image on the
23 | dmg you must also update the create-dmg-installer.sh script
24 | so it is moved to the proper place.
25 |
26 |
27 | Modifying the installer folder
28 | ------------------------------
29 |
30 | The installer is nothing more then a Finder folder view
31 | with hidden sidebar, toolbar and statusbar.
32 |
33 | Mount an disk image in RW mode (pass the --keep-temp option to
34 | create-dmg-installer.sh to keep the temporary uncompressed image)
35 | and open the Show View Options.
36 | Select the Picture background you want (from the dmg itself). Hint: use
37 | Command-Shift-. to show hidden files in the Open dialog. From the
38 | View Options also select the proper icon size to match the background
39 | position indicators. Then move the .app and /Applications symlink
40 | icons to their specified place on the background.
41 |
42 | Resize the finder window (without the toolbar, sidebar, ...) so it
43 | fits the background. Position the window somewhere on the top left
44 | in the 1024, 768 rect so it can fit on small monitors.
45 |
46 | Eject the image so .DS_Store is flushed. Then re-mount it and copy the
47 | .DS_Store, and background image to this directory.
48 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/Documentation.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/xraylib/xrayhelp.py:
--------------------------------------------------------------------------------
1 | #Copyright (c) 2009, Bruno Golosio, Antonio Brunetti, Manuel Sanchez del Rio, Tom Schoonjans and Teemu Ikonen
2 | #All rights reserved.
3 |
4 | #Redistribution and use in source and binary forms, with or without
5 | #modification, are permitted provided that the following conditions are met:
6 | # * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 | # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 | # * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
9 |
10 | #THIS SOFTWARE IS PROVIDED BY Bruno Golosio, Antonio Brunetti, Manuel Sanchez del Rio, Tom Schoonjans and Teemu Ikonen ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruno Golosio, Antonio Brunetti, Manuel Sanchez del Rio, Tom Schoonjans and Teemu Ikonen BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11 |
12 |
13 | from __future__ import print_function
14 | import string
15 |
16 | def display_func(func_name):
17 | fp = open('/usr/local/share/xraylib/xrayhelp.txt', 'r')
18 | file_lines = fp.readlines()
19 | fp.close()
20 | for i in range(len(file_lines)):
21 | line = file_lines[i].strip()
22 | if (line == func_name):
23 | while (line != ""):
24 | i = i + 1
25 | line = file_lines[i].strip()
26 | print (line)
27 | return
28 | print ()
29 | print ("Function not recognized")
30 | print ()
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/oasys/util/custom_distribution.py:
--------------------------------------------------------------------------------
1 | import numpy
2 |
3 | class CustomDistribution(object):
4 | """
5 | draws samples from a one dimensional probability distribution,
6 | by means of inversion of a discrete inverstion of a cumulative density function
7 |
8 | the pdf can be sorted first to prevent numerical error in the cumulative sum
9 | this is set as default; for big density functions with high contrast,
10 | it is absolutely necessary, and for small density functions,
11 | the overhead is minimal
12 |
13 | a call to this distibution object returns indices into density array
14 | """
15 | def __init__(self, pdf, sort = False, interpolation = False, transform = lambda x: x, seed=0):
16 | self.shape = pdf.shape
17 | self.pdf = pdf.ravel()
18 | self.sort = sort
19 | self.interpolation = interpolation
20 | self.transform = transform
21 | self.seed = seed
22 |
23 | #a pdf can not be negative
24 | assert(numpy.all(pdf>=0))
25 |
26 | #sort the pdf by magnitude
27 | if self.sort:
28 | self.sortindex = numpy.argsort(self.pdf, axis=None)
29 | self.pdf = self.pdf[self.sortindex]
30 | #construct the cumulative distribution function
31 | self.cdf = numpy.cumsum(self.pdf)
32 | @property
33 | def ndim(self):
34 | return len(self.shape)
35 | @property
36 | def sum(self):
37 | """cached sum of all pdf values; the pdf need not sum to one, and is imlpicitly normalized"""
38 | return self.cdf[-1]
39 | def __call__(self, N):
40 | if self.seed > 0: numpy.random.seed(self.seed)
41 |
42 | """draw """
43 | #pick numbers which are uniformly random over the cumulative distribution function
44 | choice = numpy.random.uniform(high = self.sum, size = N)
45 | #find the indices corresponding to this point on the CDF
46 | index = numpy.searchsorted(self.cdf, choice)
47 | #if necessary, map the indices back to their original ordering
48 | if self.sort:
49 | index = self.sortindex[index]
50 | #map back to multi-dimensional indexing
51 | index = numpy.unravel_index(index, self.shape)
52 | index = numpy.vstack(index)
53 | #is this a discrete or piecewise continuous distribution?
54 | if self.interpolation:
55 | index = index + numpy.random.uniform(size=index.shape)
56 | return self.transform(index)
57 |
--------------------------------------------------------------------------------
/scripts/macos/skeleton.app/Contents/Frameworks/xraylib/xraymessages.py:
--------------------------------------------------------------------------------
1 |
2 | #Copyright (c) 2009, Bruno Golosio, Antonio Brunetti, Manuel Sanchez del Rio, Tom Schoonjans and Teemu Ikonen
3 | #All rights reserved.
4 |
5 | #Redistribution and use in source and binary forms, with or without
6 | #modification, are permitted provided that the following conditions are met:
7 | # * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 | # * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | #THIS SOFTWARE IS PROVIDED BY Bruno Golosio, Antonio Brunetti, Manuel Sanchez del Rio, Tom Schoonjans and Teemu Ikonen ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruno Golosio, Antonio Brunetti, Manuel Sanchez del Rio, Tom Schoonjans and Teemu Ikonen BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 |
13 | from __future__ import print_function
14 | import sys
15 |
16 | def display_banner():
17 | print ()
18 | fp = open('/usr/local/share/xraylib/xraybanner.txt', 'r')
19 | for line in fp.readlines():
20 | print (line, end="")
21 | fp.close()
22 | print ()
23 |
24 | def display_options():
25 | print ()
26 | print (" - Type 'xraylib -h' to see a list of the available functions")
27 | print (" - Type 'xraylib -d' to see the X-ray data documentation")
28 | print (" - Type 'xraylib -f function-name' to get help on a" \
29 | " specific function")
30 |
31 | def display_usage():
32 | print ()
33 | print (" usage: xraylib 'expression'")
34 | print (" where 'expression' is any mathematical expression")
35 | print (" that can contain X-ray library functions.")
36 | display_options()
37 |
38 | def display_help():
39 | print ()
40 | print ("Available X-ray library functions")
41 | print ()
42 | fp = open('/usr/local/share/xraylib/xrayfunc.txt', 'r')
43 | for line in fp.readlines():
44 | print (line, end="")
45 | fp.close()
46 | display_usage()
47 |
48 | def display_doc():
49 | print ()
50 | print ("X-ray data documentation")
51 | print ()
52 | fp = open('/usr/local/share/xraylib/xraydoc.txt', 'r')
53 | for line in fp.readlines():
54 | print (line, end="")
55 | fp.close()
56 | print ()
57 |
58 |
--------------------------------------------------------------------------------
/oasys/util/external_command.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import logging
4 | import errno
5 | import shlex
6 | import subprocess
7 |
8 | log = logging.getLogger(__name__)
9 |
10 | class CommandFailed(Exception):
11 | def __init__(self, cmd, retcode, output):
12 | if not isinstance(cmd, str):
13 | cmd = " ".join(map(shlex.quote, cmd))
14 | self.cmd = cmd
15 | self.retcode = retcode
16 | self.output = output
17 |
18 | def run_command(command, raise_on_fail=True, wait_for_output=True):
19 | """Run command in a subprocess.
20 |
21 | Return `process` return code and output once it completes.
22 | """
23 | log.info("Running %s", " ".join(command))
24 |
25 | if command[0] == "python": process = python_process(command[1:])
26 | else:process = create_process(command)
27 |
28 | if wait_for_output:
29 | output = []
30 | while process.poll() is None:
31 | try:
32 | line = process.stdout.readline()
33 | except IOError as ex:
34 | if ex.errno != errno.EINTR:
35 | raise
36 | else:
37 | output.append(line)
38 | print(line, end="")
39 | # Read remaining output if any
40 | line = process.stdout.read()
41 | if line:
42 | output.append(line)
43 | print(line, end="")
44 |
45 | if process.returncode != 0:
46 | log.info("Command %s failed with %s",
47 | " ".join(command), process.returncode)
48 | log.debug("Output:\n%s", "\n".join(output))
49 | if raise_on_fail:
50 | raise CommandFailed(command, process.returncode, output)
51 |
52 | return process.returncode, output
53 |
54 |
55 | def python_process(args, script_name=None, **kwargs):
56 | """
57 | Run a `sys.executable` in a subprocess with `args`.
58 | """
59 | executable = sys.executable
60 | if os.name == "nt" and os.path.basename(executable) == "pythonw.exe":
61 | # Don't run the script with a 'gui' (detached) process.
62 | dirname = os.path.dirname(executable)
63 | executable = os.path.join(dirname, "python.exe")
64 |
65 | if script_name is not None:
66 | script = script_name
67 | else:
68 | script = executable
69 |
70 | return create_process(
71 | [script] + args,
72 | executable=executable
73 | )
74 |
75 |
76 | def create_process(cmd, executable=None, **kwargs):
77 | if hasattr(subprocess, "STARTUPINFO"):
78 | # do not open a new console window for command on windows
79 | startupinfo = subprocess.STARTUPINFO()
80 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
81 | kwargs["startupinfo"] = startupinfo
82 |
83 | return subprocess.Popen(
84 | cmd,
85 | executable=executable,
86 | cwd=None,
87 | stderr=subprocess.STDOUT,
88 | stdout=subprocess.PIPE,
89 | bufsize=-1,
90 | universal_newlines=True,
91 | **kwargs
92 | )
93 |
--------------------------------------------------------------------------------
/scripts/macos/sign-dmg.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | shopt -s failglob
5 |
6 | usage() {
7 | echo "sign-dmg.sh [-s IDENTITY] [-o OUTPUT] PATH
8 |
9 | Sign a .dmg application installer at 'path'.
10 |
11 | \`path\` must name a .dmg image.
12 |
13 | OPTIONS
14 | --sign -s IDENTITY
15 | Signing identity to use. The \`identity\` must name a signing
16 | certificate in a macOS keychain (see \`man codesign\` SIGNING
17 | IDENTITIES section for details)
18 |
19 | --output -o PATH
20 | Specify the output path for the resulting .dmg installer. If not
21 | supplied, then the signed dmg image is placed next to the input path
22 | with the same name and .signed appended at the end.
23 |
24 | --help -h
25 | Show this help.
26 |
27 | EXAMPLES
28 | $ ./sign-dmg.sh -s \"Developer ID\" SupperApp.dmg
29 | "
30 | }
31 |
32 | IDENTITY="Developer ID"
33 | OUTPUT=
34 |
35 | while true; do
36 | case "${1}" in
37 | -s|--sign) IDENTITY=${2:?"no identity provided"}; shift 2;;
38 | -o|--output) OUTPUT=${2:?"${1} requires a path parameter"}; shift 2;;
39 | -h|--help) usage; exit 0 ;;
40 | -*) echo "Unrecognized parameter: ${1}" >&2; echo; usage >&2; exit 1;;
41 | *) break;;
42 | esac
43 | done
44 |
45 | DMG="${1:?"Missing positional argument: PATH"}"
46 |
47 | if [ ! -f "${DMG}" ]; then
48 | echo "${DMG} does not exist or is not a file." >&2;
49 | exit 1
50 | fi
51 |
52 | # Temporary work directory
53 | WORKDIR=
54 | # Temporary mount point for the dmg
55 | MOUNT=
56 |
57 | cleanup() {
58 | if [ -d "${MOUNT}" ]; then hdiutil detach "${MOUNT}" -force || true; fi
59 | if [ -d "${WORKDIR}" ]; then rm -rf "${WORKDIR}"; fi
60 | return
61 | }
62 | trap cleanup EXIT
63 |
64 | BASENAME=$(basename "${DMG}")
65 | WORKDIR=$(mktemp -d -t "${BASENAME}")
66 | MOUNT=${WORKDIR}/mnt
67 |
68 | IMGRW=${WORKDIR}/image
69 | IMG=${WORKDIR}/${BASENAME}
70 |
71 | # convert the input dmg to a read write growable uncompressed image
72 | # NOTE: hdiutil convert always appends the extension on the output even if
73 | # already present (the ext for UDSB is .sparsebundle so the actual filename
74 | # is ${IMGRW}.sparsebundle)
75 | hdiutil convert -format UDSB -o "${IMGRW}" "${DMG}"
76 | # 'resize' the sparse image allowing growth for signing data
77 | # (1GB should be enough for everybody)
78 | hdiutil resize -size 1g "${IMGRW}".sparsebundle
79 | # mount it R/W for modification
80 | mkdir "${MOUNT}"
81 | hdiutil attach "${IMGRW}".sparsebundle -readwrite -noverify -noautoopen \
82 | -mountpoint "${MOUNT}"
83 |
84 | codesign --sign "${IDENTITY}" --deep --verbose "${MOUNT}"/*.app
85 |
86 | # detach/unmount to sync
87 | hdiutil detach "${MOUNT}" -force
88 | # resize the image to minimum required size
89 | hdiutil resize -sectors min "${IMGRW}".sparsebundle
90 | # convert back to compressed read only image
91 | hdiutil convert -format UDZO -imagekey zlib-level=9 \
92 | -o "${IMG}" "${IMGRW}.sparsebundle"
93 | codesign -s "${IDENTITY}" "${IMG}"
94 |
95 | if [ ! "${OUTPUT}" ]; then
96 | OUTPUT=${DMG}.signed
97 | fi
98 |
99 | mv "${IMG}" "${OUTPUT}"
100 |
--------------------------------------------------------------------------------
/oasys/menus/menu.py:
--------------------------------------------------------------------------------
1 | __author__ = 'labx'
2 | __menu__="just for discovery"
3 |
4 | SEPARATOR = "OMENU_SEPARATOR"
5 | OPEN_CONTAINER = "OPEN_CONTAINER"
6 | CLOSE_CONTAINER = "CLOSE_CONTAINER"
7 |
8 |
9 | from PyQt5 import QtWidgets
10 | from orangecanvas.scheme.link import SchemeLink
11 |
12 | class OMenu():
13 |
14 | def __init__(self, name="NewMenu"):
15 | self.name = name
16 | self.canvas_main_window=None
17 | self.sub_menu_names = []
18 |
19 | def setCanvasMainWindow(self, canvas_main_window):
20 | self.canvas_main_window = canvas_main_window
21 |
22 | def addSubMenu(self, name):
23 | self.sub_menu_names.append(name)
24 |
25 | def addSeparator(self):
26 | self.sub_menu_names.append(SEPARATOR)
27 |
28 | def openContainer(self):
29 | self.sub_menu_names.append(OPEN_CONTAINER)
30 |
31 | def closeContainer(self):
32 | self.sub_menu_names.append(CLOSE_CONTAINER)
33 |
34 | def addContainer(self, name):
35 | self.sub_menu_names.append(name)
36 |
37 | def isSeparator(self, name):
38 | return name == SEPARATOR
39 |
40 | def isOpenContainer(self, name):
41 | return name == OPEN_CONTAINER
42 |
43 | def isCloseContainer(self, name):
44 | return name == CLOSE_CONTAINER
45 |
46 | def getSubMenuNamesList(self):
47 | return self.sub_menu_names
48 |
49 | def showConfirmMessage(self, message, informative_text=None):
50 | msgBox = QtWidgets.QMessageBox()
51 | msgBox.setIcon(QtWidgets.QMessageBox.Question)
52 | msgBox.setText(message)
53 | msgBox.setInformativeText(message if informative_text is None else informative_text)
54 | msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
55 | msgBox.setDefaultButton(QtWidgets.QMessageBox.No)
56 | ret = msgBox.exec_()
57 | return ret
58 |
59 | def showWarningMessage(self, message):
60 | msgBox = QtWidgets.QMessageBox()
61 | msgBox.setIcon(QtWidgets.QMessageBox.Warning)
62 | msgBox.setText(message)
63 | msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
64 | msgBox.exec_()
65 |
66 | def showCriticalMessage(self, message):
67 | msgBox = QtWidgets.QMessageBox()
68 | msgBox.setIcon(QtWidgets.QMessageBox.Critical)
69 | msgBox.setText(message)
70 | msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
71 | msgBox.exec_()
72 |
73 | def getWidgetFromNode(self, node):
74 | return self.canvas_main_window.current_document().scheme().widget_for_node(node)
75 |
76 | def createLinks(self, nodes, excluded_names=[], source_channel="In", sink_channel="Out"):
77 | previous_node = None
78 | for node in nodes:
79 | if not (isinstance(node, str) and node in excluded_names):
80 | if not previous_node is None :
81 | if not (isinstance(previous_node, str) and previous_node in excluded_names):
82 | link = SchemeLink(source_node=previous_node, source_channel=source_channel, sink_node=node, sink_channel=sink_channel)
83 | self.canvas_main_window.current_document().addLink(link=link)
84 | previous_node = node
85 |
86 | def getWidgetDesc(self, widget_name, excluded_names=[]):
87 | if widget_name in excluded_names: return widget_name
88 | else: return self.canvas_main_window.widget_registry.widget(widget_name)
89 |
90 | def createNewNode(self, widget_desc):
91 | return self.canvas_main_window.current_document().createNewNode(widget_desc)
92 |
93 |
94 |
--------------------------------------------------------------------------------
/oasys/widgets/congruence.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | def checkNumber(value, field_name):
4 | try:
5 | float(value)
6 | except ValueError:
7 | raise Exception(str(field_name) + " is not a number")
8 |
9 | return value
10 |
11 | def checkPositiveNumber(value, field_name):
12 | value = checkNumber(value, field_name)
13 | if (value < 0): raise Exception(field_name + " should be >= 0")
14 |
15 | return value
16 |
17 | def checkStrictlyPositiveNumber(value, field_name):
18 | value = checkNumber(value, field_name)
19 | if (value <= 0): raise Exception(field_name + " should be > 0")
20 |
21 | return value
22 |
23 | def checkAngle(value, field_name):
24 | value = checkNumber(value, field_name)
25 | if value < -360 or value > 360: raise Exception(field_name + " should be >= -360 and <= 360 deg")
26 |
27 | return value
28 |
29 | def checkPositiveAngle(value, field_name):
30 | value = checkNumber(value, field_name)
31 | if value < 0 or value > 360: raise Exception(field_name + " should be >= 0 and <= 360 deg")
32 |
33 | return value
34 |
35 | def checkStrictlyPositiveAngle(value, field_name):
36 | value = checkNumber(value, field_name)
37 | if value <= 0 or value >= 360: raise Exception(field_name + " should be > 0 and < 360 deg")
38 |
39 | return value
40 |
41 | def checkEmptyString(string, field_name):
42 | if string is None: raise Exception(field_name + " should not be an empty string")
43 | if string.strip() == "": raise Exception(field_name + " should not be an empty string")
44 |
45 | return string
46 |
47 | def checkGreaterThan(number1, number2, field_name1, field_name_2):
48 | if number1 <= number2: raise Exception(field_name1 + " should be greater than " + field_name_2)
49 |
50 | def checkGreaterOrEqualThan(number1, number2, field_name1, field_name_2):
51 | if number1 < number2: raise Exception(field_name1 + " should be greater or equal than " + field_name_2)
52 |
53 | def checkLessThan(number1, number2, field_name1, field_name_2):
54 | if number1 >= number2: raise Exception(field_name1 + " should be less than " + field_name_2)
55 |
56 | def checkLessOrEqualThan(number1, number2, field_name1, field_name_2):
57 | if number1 > number2: raise Exception(field_name1 + " should be less or equal than " + field_name_2)
58 |
59 | def checkEqualTo(number1, number2, field_name1, field_name_2):
60 | if number1 != number2: raise Exception(field_name1 + " should be equal to " + field_name_2)
61 |
62 | def checkFileName(fileName):
63 | if isinstance(fileName, bytes): fileName = fileName.decode('utf-8')
64 |
65 | if fileName is None: raise Exception("File name is Empty")
66 | if fileName.strip() == "": raise Exception("File name is Empty")
67 |
68 | if os.path.isabs(fileName):
69 | filePath = fileName
70 | else:
71 | if fileName.startswith(os.path.sep):
72 | filePath = os.getcwd() + fileName
73 | else:
74 | filePath = os.getcwd() + os.path.sep + fileName
75 |
76 | return filePath
77 |
78 | def checkDir(fileName):
79 | if isinstance(fileName, bytes): fileName = fileName.decode('utf-8')
80 |
81 | filePath = checkFileName(fileName)
82 |
83 | container_dir = os.path.dirname(filePath)
84 |
85 | if not os.path.exists(container_dir):
86 | raise Exception("Directory " + container_dir + " not existing")
87 |
88 | return filePath
89 |
90 | def checkFile(fileName):
91 | if isinstance(fileName, bytes): fileName = fileName.decode('utf-8')
92 |
93 | filePath = checkDir(fileName)
94 |
95 | if not os.path.exists(filePath):
96 | raise Exception("File " + fileName + " not existing")
97 |
98 | return filePath
99 |
100 |
101 | def checkUrl(myfileurl):
102 | from urllib.request import urlopen
103 | try:
104 | u = urlopen(myfileurl)
105 | except:
106 | try:
107 | return checkFile(myfileurl)
108 | except:
109 | raise Exception("URL or File not accessible: "+myfileurl)
110 |
111 | return myfileurl
112 |
--------------------------------------------------------------------------------
/oasys/widgets/scanning/ow_scan_file_node_point.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # #########################################################################
4 | # Copyright (c) 2020, UChicago Argonne, LLC. All rights reserved. #
5 | # #
6 | # Copyright 2020. UChicago Argonne, LLC. This software was produced #
7 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National #
8 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the #
9 | # U.S. Department of Energy. The U.S. Government has rights to use, #
10 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR #
11 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR #
12 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is #
13 | # modified to produce derivative works, such modified software should #
14 | # be clearly marked, so as not to confuse it with the version available #
15 | # from ANL. #
16 | # #
17 | # Additionally, redistribution and use in source and binary forms, with #
18 | # or without modification, are permitted provided that the following #
19 | # conditions are met: #
20 | # #
21 | # * Redistributions of source code must retain the above copyright #
22 | # notice, this list of conditions and the following disclaimer. #
23 | # #
24 | # * Redistributions in binary form must reproduce the above copyright #
25 | # notice, this list of conditions and the following disclaimer in #
26 | # the documentation and/or other materials provided with the #
27 | # distribution. #
28 | # #
29 | # * Neither the name of UChicago Argonne, LLC, Argonne National #
30 | # Laboratory, ANL, the U.S. Government, nor the names of its #
31 | # contributors may be used to endorse or promote products derived #
32 | # from this software without specific prior written permission. #
33 | # #
34 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS #
35 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #
36 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS #
37 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago #
38 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
39 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #
40 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #
41 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
42 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT #
43 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #
44 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
45 | # POSSIBILITY OF SUCH DAMAGE. #
46 | # #########################################################################
47 |
48 | from oasys.widgets.abstract.scanning.abstract_scan_file_node_point import AbstractScanFileLoopPoint
49 |
50 | class ScanFileLoopPoint(AbstractScanFileLoopPoint):
51 |
52 | name = "Scanning File Loop Point"
53 | description = "Tools: LoopPoint"
54 | icon = "icons/cycle_file.png"
55 | maintainer = "Luca Rebuffi"
56 | maintainer_email = "lrebuffi(@at@)anl.gov"
57 | priority = 2
58 | category = "User Defined"
59 | keywords = ["data", "file", "load", "read"]
60 |
61 | def __init__(self):
62 | super(ScanFileLoopPoint, self).__init__()
63 |
64 | import sys
65 | from PyQt5.QtWidgets import QApplication
66 |
67 | if __name__ == "__main__":
68 | a = QApplication(sys.argv)
69 | ow = ScanFileLoopPoint()
70 | ow.show()
71 | a.exec_()
72 | ow.saveSettings()
73 |
--------------------------------------------------------------------------------
/oasys/widgets/scanning/ow_scan_variable_node_point.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # #########################################################################
4 | # Copyright (c) 2020, UChicago Argonne, LLC. All rights reserved. #
5 | # #
6 | # Copyright 2020. UChicago Argonne, LLC. This software was produced #
7 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National #
8 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the #
9 | # U.S. Department of Energy. The U.S. Government has rights to use, #
10 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR #
11 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR #
12 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is #
13 | # modified to produce derivative works, such modified software should #
14 | # be clearly marked, so as not to confuse it with the version available #
15 | # from ANL. #
16 | # #
17 | # Additionally, redistribution and use in source and binary forms, with #
18 | # or without modification, are permitted provided that the following #
19 | # conditions are met: #
20 | # #
21 | # * Redistributions of source code must retain the above copyright #
22 | # notice, this list of conditions and the following disclaimer. #
23 | # #
24 | # * Redistributions in binary form must reproduce the above copyright #
25 | # notice, this list of conditions and the following disclaimer in #
26 | # the documentation and/or other materials provided with the #
27 | # distribution. #
28 | # #
29 | # * Neither the name of UChicago Argonne, LLC, Argonne National #
30 | # Laboratory, ANL, the U.S. Government, nor the names of its #
31 | # contributors may be used to endorse or promote products derived #
32 | # from this software without specific prior written permission. #
33 | # #
34 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS #
35 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #
36 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS #
37 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago #
38 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
39 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #
40 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #
41 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
42 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT #
43 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #
44 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
45 | # POSSIBILITY OF SUCH DAMAGE. #
46 | # #########################################################################
47 |
48 | from oasys.widgets.abstract.scanning.abstract_scan_variable_node_point import AbstractScanVariableLoopPoint
49 |
50 | class ScanVariableLoopPoint(AbstractScanVariableLoopPoint):
51 |
52 | name = "Scanning Variable Loop Point"
53 | description = "Tools: LoopPoint"
54 | icon = "icons/cycle_variable.png"
55 | maintainer = "Luca Rebuffi"
56 | maintainer_email = "lrebuffi(@at@)anl.gov"
57 | priority = 1
58 | category = "User Defined"
59 | keywords = ["data", "file", "load", "read"]
60 |
61 | def __init__(self):
62 | super(ScanVariableLoopPoint, self).__init__()
63 |
64 | import sys
65 | from PyQt5.QtWidgets import QApplication
66 |
67 | if __name__ == "__main__":
68 | a = QApplication(sys.argv)
69 | ow = ScanVariableLoopPoint()
70 | ow.show()
71 | a.exec_()
72 | ow.saveSettings()
73 |
--------------------------------------------------------------------------------
/scripts/macos/create-dmg-installer.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | function print_usage() {
6 | echo 'create-dmg-installer.sh --app BUILD_APP_PATH OUTPUT_BUNDLE.dmg
7 |
8 | Create an disk image installer (.dmg) for Orange OSX application.
9 |
10 | Options:
11 | -a --app PATH
12 | Path to a build Orange3.app to include in the disk image
13 | (default dist/Orange3.app)
14 |
15 | -s --sign IDENTITY
16 | Sign the application and the .dmg image using the signing identity
17 | provided (see `man codesign` SIGNING IDENTITIES section for details)
18 |
19 | -k --keep-temp
20 | Keep the temporary files after creating the final image.
21 |
22 | -h --help
23 | Print this help
24 | '
25 | }
26 |
27 |
28 | DIRNAME=$(dirname "$0")
29 |
30 | # Path to dmg resources (volume icon, background, ...)
31 | RES="${DIRNAME}"/dmg-resources
32 |
33 | APP=dist/Oasys1.2.app
34 |
35 | KEEP_TEMP=0
36 | IDENTITY=
37 |
38 | while [[ "${1:0:1}" = "-" ]]; do
39 | case "${1}" in
40 | -a|--app)
41 | APP=${2:?"BUILD_APP_PATH is missing"}
42 | shift 2 ;;
43 | -k|--keep-temp)
44 | KEEP_TEMP=1
45 | shift 1 ;;
46 | -s|--sign)
47 | IDENTITY=${2:?"${1} is missing a parameter"}
48 | shift 2;;
49 | -h|--help)
50 | print_usage
51 | exit 0 ;;
52 | -*)
53 | echo "Unknown option $1" >&2
54 | print_usage
55 | exit 1
56 | ;;
57 | esac
58 | done
59 |
60 | DMG=${1?"Output bundle dmg path not specified"}
61 |
62 |
63 | if [[ ! -d "${APP}" ]]; then
64 | echo "$APP path does not exits or is not a directory."
65 | print_usage
66 | exit 1
67 | fi
68 |
69 | TMP_DIR=$(mktemp -d -t create-dmg-installer)
70 | TMP_TEMPLATE="${TMP_DIR}"/template
71 | TMP_DMG="${TMP_DIR}"/Oasys1.2.dmg
72 | TMP_MOUNT="${TMP_DIR}"/mnt
73 |
74 | echo "Preparing an image template in ${TMP_TEMPLATE}"
75 | echo "============================================="
76 |
77 | # Copy necessary resources into the template
78 |
79 | mkdir -p "${TMP_TEMPLATE}"/.background
80 |
81 | cp -a "${RES}"/background.png "${TMP_TEMPLATE}"/.background
82 | cp -a "${RES}"/VolumeIcon.icns "${TMP_TEMPLATE}"/.VolumeIcon.icns
83 | cp -a "${RES}"/DS_Store "${TMP_TEMPLATE}"/.DS_Store
84 |
85 | # Create a link to the Applications folder.
86 | ln -s /Applications/ "${TMP_TEMPLATE}"/Applications
87 |
88 | # Copy the .app directory in place
89 | cp -a "${APP}" "${TMP_TEMPLATE}"/Oasys1.2.app
90 |
91 | if [[ "${IDENTITY}" ]]; then
92 | codesign -s "${IDENTITY}" --deep --verbose \
93 | "${TMP_TEMPLATE}"/Oasys1.2.app
94 | fi
95 |
96 | # Create a regular .fseventsd/no_log file
97 | # (see http://hostilefork.com/2009/12/02/trashes-fseventsd-and-spotlight-v100/ )
98 |
99 | mkdir "${TMP_TEMPLATE}"/.fseventsd
100 | touch "${TMP_TEMPLATE}"/.fseventsd/no_log
101 |
102 |
103 | echo "Creating a temporary disk image"
104 | hdiutil create -format UDRW -volname Oasys1.2 -fs HFS+ \
105 | -fsargs "-c c=64,a=16,e=16" \
106 | -srcfolder "${TMP_TEMPLATE}" \
107 | "${TMP_DMG}"
108 |
109 | mkdir "${TMP_MOUNT}"
110 |
111 | # Mount in RW mode
112 | echo "Mounting temporary disk image"
113 | hdiutil attach -readwrite -noverify -noautoopen -mountpoint "${TMP_MOUNT}" \
114 | "${TMP_DMG}"
115 |
116 | echo "Fixing permissions"
117 | chmod -Rf go-w "${TMP_TEMPLATE}" || true
118 |
119 | # Makes the disk image window open automatically when mounted
120 | bless -openfolder "${TMP_MOUNT}"
121 |
122 | # Hides background directory even more
123 | SetFile -a V "${TMP_MOUNT}/.background/"
124 |
125 | # Sets the custom icon volume flag so that volume has nice
126 | # Orange icon after mount (.VolumeIcon.icns)
127 | SetFile -a C "${TMP_MOUNT}"
128 |
129 | echo "Unmouting the temporary image"
130 | sync
131 | hdiutil detach "${TMP_MOUNT}" -verbose -force
132 |
133 | echo "Converting temporary image to a compressed image."
134 |
135 | if [[ -e "${DMG}" ]]; then rm -f "${DMG}"; fi
136 |
137 | mkdir -p "$(dirname "${DMG}")"
138 | hdiutil convert "${TMP_DMG}" -format UDZO -imagekey zlib-level=9 -o "${DMG}"
139 |
140 | if [[ "${IDENTITY}" ]]; then
141 | codesign -s "${IDENTITY}" "${DMG}"
142 | fi
143 |
144 | if [ ! ${KEEP_TEMP} ]; then
145 | echo "Cleaning up."
146 | rm -rf "${TMP_DIR}"
147 | fi
148 |
--------------------------------------------------------------------------------
/oasys/util/script/value.py:
--------------------------------------------------------------------------------
1 | from numbers import Real
2 | from math import isnan
3 |
4 | #: A constant representing unknown value (NaN). Use this for storing unknowns,
5 | #: but not for checking for unknowns.
6 | Unknown = float("nan")
7 |
8 |
9 | class Value(float):
10 | """
11 | The class representing a value. The class is not used to store values but
12 | only to return them in contexts in which we want the value to be accompanied
13 | with the descriptor, for instance to print the symbolic value of discrete
14 | variables.
15 |
16 | The class is derived from `float`, with an additional attribute `variable`
17 | which holds the descriptor of type :obj:`Orange.data.Variable`. If the
18 | value continuous or discrete, it is stored as a float. Other types of
19 | values, like strings, are stored in the attribute `value`.
20 |
21 | The class overloads the methods for printing out the value:
22 | `variable.repr_val` and `variable.str_val` are used to get a suitable
23 | representation of the value.
24 |
25 | Equivalence operator is overloaded as follows:
26 |
27 | - unknown values are equal; if one value is unknown and the other is not,
28 | they are different;
29 |
30 | - if the value is compared with the string, the value is converted to a
31 | string using `variable.str_val` and the two strings are compared
32 |
33 | - if the value is stored in attribute `value`, it is compared with the
34 | given other value
35 |
36 | - otherwise, the inherited comparison operator for `float` is called.
37 |
38 | Finally, value defines a hash, so values can be put in sets and appear as
39 | keys in dictionaries.
40 |
41 | .. attribute:: variable (:obj:`Orange.data.Variable`)
42 |
43 | Descriptor; used for printing out and for comparing with strings
44 |
45 | .. attribute:: value
46 |
47 | Value; the value can be of arbitrary type and is used only for variables
48 | that are neither discrete nor continuous. If `value` is `None`, the
49 | derived `float` value is used.
50 | """
51 | __slots__ = "variable", "_value"
52 |
53 | def __new__(cls, variable, value=Unknown):
54 | """
55 | Construct a new instance of Value with the given descriptor and value.
56 | If the argument `value` can be converted to float, it is stored as
57 | `float` and the attribute `value` is set to `None`. Otherwise, the
58 | inherited float is set to `Unknown` and the value is held by the
59 | attribute `value`.
60 |
61 | :param variable: descriptor
62 | :type variable: Orange.data.Variable
63 | :param value: value
64 | """
65 | if not isinstance(value, str):
66 | try:
67 | self = super().__new__(cls, value)
68 | self.variable = variable
69 | return self
70 | except:
71 | pass
72 | self = super().__new__(cls, -1)
73 | self._value = value
74 | self.variable = variable
75 | return self
76 |
77 | def __init__(self, _, __=Unknown):
78 | pass
79 |
80 | def __repr__(self):
81 | return "Value('%s', %s)" % (self.variable.name,
82 | self.variable.repr_val(self))
83 |
84 | def __str__(self):
85 | return self.variable.str_val(self)
86 |
87 | def __eq__(self, other):
88 | if isinstance(self, Real) and isnan(self):
89 | return (isinstance(other, Real) and isnan(other)
90 | or other in self.variable.unknown_str)
91 | if isinstance(other, str):
92 | return self.variable.str_val(self) == other
93 | if isinstance(other, Value):
94 | return self.value == other.value
95 | return super().__eq__(other)
96 |
97 | def __contains__(self, other):
98 | if (self.value is not None
99 | and isinstance(self.value, str)
100 | and isinstance(other, str)):
101 | return other in self.value
102 | raise TypeError("invalid operation on Value()")
103 |
104 | def __hash__(self):
105 | if self.value is None:
106 | return super().__hash__(self)
107 | else:
108 | return super().__hash__(self) ^ hash(self.value)
109 |
110 | @property
111 | def value(self):
112 | from . import DiscreteVariable, StringVariable
113 | if isinstance(self.variable, DiscreteVariable):
114 | return self.variable.values[int(self)]
115 | if isinstance(self.variable, StringVariable):
116 | return self._value
117 | return float(self)
118 |
119 | def __getnewargs__(self):
120 | return self.variable, float(self)
121 |
122 | def __getstate__(self):
123 | return dict(value=getattr(self, '_value', None))
124 |
125 | def __setstate__(self, state):
126 | self._value = state.get('value', None)
127 |
--------------------------------------------------------------------------------
/oasys/canvas/conf.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import sys
3 | # 17 Jan 2025: replaced pkg_resources with importlib (for now the third party version)
4 | # because of deprecation
5 | #import pkg_resources
6 | import importlib_resources
7 | import importlib_metadata
8 |
9 | from PyQt5.QtGui import QPixmap, QFont, QFontMetrics, QColor, QPainter, QIcon
10 | from PyQt5.QtCore import Qt, QCoreApplication, QPoint, QRect
11 |
12 | from orangewidget.canvas import config as owconfig
13 | from orangecanvas import config
14 |
15 | from . import discovery, widgetsscheme
16 |
17 |
18 | WIDGETS_ENTRY = "oasys.widgets"
19 | MENU_ENTRY = "oasys.menus"
20 |
21 | #: Parameters for searching add-on packages in PyPi using xmlrpc api.
22 | ADDON_PYPI_SEARCH_SPEC = {"keywords": "oasys1", "owner" : "lucarebuffi"}
23 | #: Entry points by which add-ons register with pkg_resources.
24 | ADDONS_ENTRY = "oasys.addons"
25 |
26 | # Add a default for our extra default-working-dir setting.
27 | config.spec += [
28 | config.config_slot("output/default-working-dir", str, "",
29 | "Default working directory"),
30 | config.config_slot("oasys/addon-update-check-period", int, 1,
31 | "Check for updates every (in days)")
32 | ]
33 |
34 | class oasysconf(owconfig.orangeconfig):
35 | OrganizationDomain = ""
36 | ApplicationName = "OASYS1"
37 |
38 | if sys.platform == 'darwin' and sys.version_info[1] <= 6:
39 | ApplicationVersion = "1.1"
40 | else:
41 | if sys.version[:3]=="3.8":
42 | ApplicationVersion = "1.3"
43 | else:
44 | ApplicationVersion = "1.2"
45 |
46 | @staticmethod
47 | def splash_screen():
48 | ref = importlib_resources.files(__name__).joinpath("icons/oasys-splash-screen.png")
49 | with importlib_resources.as_file(ref) as path: pm = QPixmap(str(path))
50 |
51 | version = QCoreApplication.applicationVersion()
52 | size = 21 if len(version) < 5 else 16
53 | font = QFont("Helvetica")
54 | font.setPixelSize(size)
55 | font.setBold(True)
56 | font.setItalic(True)
57 | font.setLetterSpacing(QFont.AbsoluteSpacing, 2)
58 | metrics = QFontMetrics(font)
59 | br = metrics.boundingRect(version).adjusted(-5, 0, 5, 0)
60 | br.moveCenter(QPoint(436, 224))
61 |
62 | p = QPainter(pm)
63 | p.setRenderHint(QPainter.Antialiasing)
64 | p.setRenderHint(QPainter.TextAntialiasing)
65 | p.setFont(font)
66 | p.setPen(QColor("#231F20"))
67 | p.drawText(br, Qt.AlignCenter, version)
68 | p.end()
69 | return pm, QRect(88, 193, 200, 20)
70 |
71 | @staticmethod
72 | def application_icon():
73 | """
74 | Return the main application icon.
75 | """
76 | ref = importlib_resources.files(__name__).joinpath("icons/oasys.png")
77 | with importlib_resources.as_file(ref) as path: return QIcon(str(path))
78 |
79 | @staticmethod
80 | def widgets_entry_points():
81 | # 17 Jan 2025: replaced pkg_resources with importlib (for now the third party version)
82 | # because of deprecation
83 | return importlib_metadata.entry_points(group=WIDGETS_ENTRY)
84 | #return pkg_resources.iter_entry_points(WIDGETS_ENTRY)
85 |
86 | @staticmethod
87 | def addon_entry_points():
88 | # 17 Jan 2025: replaced pkg_resources with importlib (for now the third party version)
89 | # because of deprecation
90 | return importlib_metadata.entry_points(group=ADDONS_ENTRY)
91 | #return pkg_resources.iter_entry_points(ADDONS_ENTRY)
92 |
93 | @staticmethod
94 | def addon_pypi_search_spec():
95 | return dict(ADDON_PYPI_SEARCH_SPEC)
96 |
97 | @staticmethod
98 | def tutorials_entry_points():
99 | # 17 Jan 2025: replaced pkg_resources with importlib (for now the third party version)
100 | # because of deprecation
101 | return importlib_metadata.entry_points(group="oasys.tutorials")
102 | #return pkg_resources.iter_entry_points("oasys.tutorials")
103 |
104 | workflow_constructor = widgetsscheme.OASYSWidgetsScheme
105 |
106 |
107 | def omenus():
108 | """
109 | Return an iterator of oasys.menu.OMenu instances registered
110 | by 'orange.menu' pkg_resources entry point.
111 | """
112 | log = logging.getLogger(__name__)
113 | # 17 Jan 2025: replaced pkg_resources with importlib (for now the third party version)
114 | # because of deprecation
115 | #for ep in pkg_resources.iter_entry_points(MENU_ENTRY):
116 | for ep in importlib_metadata.entry_points(group=MENU_ENTRY):
117 | try:
118 | menu = ep.load()
119 | #except pkg_resources.ResolutionError:
120 | # log.info("Error loading a '%s' entry point.", MENU_ENTRY, exc_info=True)
121 | except Exception:
122 | log.exception("Error loading a '%s' entry point.", MENU_ENTRY)
123 | else:
124 | if "MENU" in menu.__dict__:
125 | yield from discovery.omenus_from_package(menu)
126 |
127 |
128 | def menu_registry():
129 | """
130 | Return the the OASYS extension menu registry.
131 | """
132 | return discovery.MenuRegistry(list(omenus()))
133 |
--------------------------------------------------------------------------------
/oasys/widgets/tools/ow_hdf5_file_reader.py:
--------------------------------------------------------------------------------
1 | import numpy
2 |
3 | from PyQt5.QtCore import QRect
4 | from PyQt5.QtWidgets import QApplication, QMessageBox
5 |
6 | from orangewidget import gui
7 | from orangewidget.settings import Setting
8 |
9 | from oasys.widgets.widget import OWWidget
10 | from oasys.widgets import gui as oasysgui
11 | from oasys.widgets import congruence
12 |
13 | from silx.gui import qt
14 | import silx.gui.hdf5
15 | from silx.gui.data.DataViewerFrame import DataViewerFrame
16 |
17 | class Hdf5TreeViewWidget(qt.QWidget):
18 | def __init__(self, file_names=None):
19 | qt.QWidget.__init__(self)
20 |
21 | self.__treeview = silx.gui.hdf5.Hdf5TreeView(self)
22 | self.__text = qt.QTextEdit(self)
23 | self.__dataViewer = DataViewerFrame(self)
24 |
25 | vSplitter = qt.QSplitter(qt.Qt.Vertical)
26 | vSplitter.addWidget(self.__dataViewer)
27 | vSplitter.addWidget(self.__text)
28 | vSplitter.setSizes([10, 0])
29 |
30 | splitter = qt.QSplitter(self)
31 | splitter.addWidget(self.__treeview)
32 | splitter.addWidget(vSplitter)
33 | splitter.setStretchFactor(1, 1)
34 |
35 | layout = qt.QVBoxLayout()
36 | layout.addWidget(splitter)
37 | layout.setStretchFactor(splitter, 1)
38 | self.setLayout(layout)
39 |
40 | # append all files to the tree
41 | if not file_names is None:
42 | for file_name in file_names:
43 | self.__treeview.findHdf5TreeModel().appendFile(file_name)
44 |
45 | self.__treeview.activated.connect(self.displayData)
46 |
47 | def displayData(self):
48 | """Called to update the dataviewer with the selected data.
49 | """
50 | selected = list(self.__treeview.selectedH5Nodes())
51 | if len(selected) == 1:
52 | # Update the viewer for a single selection
53 | data = selected[0]
54 | self.__dataViewer.setData(data)
55 |
56 | def load_file(self, filename):
57 | self.__treeview.findHdf5TreeModel().insertFile(filename)
58 |
59 | def set_text(self, text):
60 | self.__text.setText(text)
61 |
62 | def __hdf5ComboChanged(self, index):
63 | function = self.__hdf5Combo.itemData(index)
64 | self.__createHdf5Button.setCallable(function)
65 |
66 | def __edfComboChanged(self, index):
67 | function = self.__edfCombo.itemData(index)
68 | self.__createEdfButton.setCallable(function)
69 |
70 |
71 | class OWHDF5FileReader(OWWidget):
72 | name = "HDF5 File Reader"
73 | id = "hdf5_file_reader"
74 | description = "HDF5 File Reader"
75 | icon = "icons/hdf5.png"
76 | author = "Luca Rebuffi"
77 | maintainer_email = "lrebuffi@anl.gov"
78 | priority = 2
79 | category = ""
80 | keywords = ["hdf5_file_reader"]
81 |
82 | want_main_area = 1
83 | want_control_area = 1
84 |
85 | MAX_WIDTH = 1320
86 | MAX_HEIGHT = 700
87 |
88 | IMAGE_WIDTH = 860
89 | IMAGE_HEIGHT = 645
90 |
91 | CONTROL_AREA_WIDTH = 405
92 | TABS_AREA_HEIGHT = 618
93 |
94 | hdf5_file_name = Setting('file.hdf5')
95 |
96 | def __init__(self):
97 | super().__init__()
98 |
99 | geom = QApplication.desktop().availableGeometry()
100 | self.setGeometry(QRect(round(geom.width() * 0.05),
101 | round(geom.height() * 0.05),
102 | round(min(geom.width() * 0.98, self.MAX_WIDTH)),
103 | round(min(geom.height() * 0.95, self.MAX_HEIGHT))))
104 |
105 | self.setMaximumHeight(self.geometry().height())
106 | self.setMaximumWidth(self.geometry().width())
107 |
108 | gui.separator(self.controlArea)
109 |
110 | button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")
111 |
112 | button = gui.button(button_box, self, "Load HDF5 file", callback=self.load_file)
113 | button.setFixedHeight(45)
114 |
115 | input_box_l = oasysgui.widgetBox(self.controlArea, "Input", addSpace=True, orientation="horizontal", height=self.TABS_AREA_HEIGHT)
116 |
117 | self.le_hdf5_file_name = oasysgui.lineEdit(input_box_l, self, "hdf5_file_name", "HDF5 File Name",
118 | labelWidth=120, valueType=str, orientation="horizontal")
119 |
120 | gui.button(input_box_l, self, "...", callback=self.selectPlotXYFile)
121 |
122 | self.tree_view = Hdf5TreeViewWidget()
123 |
124 | self.mainArea.layout().addWidget(self.tree_view)
125 |
126 | gui.rubber(self.mainArea)
127 |
128 |
129 | def load_file(self):
130 | try:
131 | hdf5_file_name = congruence.checkDir(self.hdf5_file_name)
132 |
133 | self.tree_view.load_file(hdf5_file_name)
134 | self.tree_view.set_text("Loaded File: " + hdf5_file_name)
135 |
136 | except Exception as exception:
137 | QMessageBox.critical(self, "Error", exception.args[0], QMessageBox.Ok)
138 |
139 | if self.IS_DEVELOP: raise exception
140 |
141 | def selectPlotXYFile(self):
142 | self.le_hdf5_file_name.setText(oasysgui.selectFileFromDialog(self, self.hdf5_file_name, "Select Input File", file_extension_filter="HDF5 Files (*.hdf5 *.h5 *.hdf)"))
143 |
144 |
145 |
--------------------------------------------------------------------------------
/oasys/widgets/tools/ow_surface_file_reader.py:
--------------------------------------------------------------------------------
1 | import os, sys
2 |
3 | import numpy
4 | from PyQt5.QtCore import QRect
5 | from PyQt5.QtWidgets import QApplication, QMessageBox
6 |
7 | from matplotlib import cm
8 | from oasys.widgets.gui import FigureCanvas3D
9 | from matplotlib.figure import Figure
10 |
11 | from orangewidget import gui
12 | from orangewidget.settings import Setting
13 |
14 | from oasys.widgets.widget import OWWidget
15 | from oasys.widgets import gui as oasysgui
16 | from oasys.widgets import congruence
17 |
18 | from oasys.util.oasys_objects import OasysSurfaceData
19 |
20 | import oasys.util.oasys_util as OU
21 |
22 | try:
23 | from mpl_toolkits.mplot3d import Axes3D # necessario per caricare i plot 3D
24 | except:
25 | pass
26 |
27 | class OWSurfaceFileReader(OWWidget):
28 | name = "Surface File Reader"
29 | id = "surface_file_reader"
30 | description = "Surface File Reader"
31 | icon = "icons/surface_reader.png"
32 | author = "Luca Rebuffi"
33 | maintainer_email = "lrebuffi@anl.gov"
34 | priority = 3
35 | category = ""
36 | keywords = ["surface_file_reader"]
37 |
38 | outputs = [{"name": "Surface Data",
39 | "type": OasysSurfaceData,
40 | "doc": "Surface Data",
41 | "id": "Surface Data"}]
42 |
43 | want_main_area = 1
44 | want_control_area = 1
45 |
46 | MAX_WIDTH = 1320
47 | MAX_HEIGHT = 700
48 |
49 | IMAGE_WIDTH = 860
50 | IMAGE_HEIGHT = 645
51 |
52 | CONTROL_AREA_WIDTH = 405
53 | TABS_AREA_HEIGHT = 618
54 |
55 | xx = None
56 | yy = None
57 | zz = None
58 |
59 | surface_file_name = Setting('surface.hdf5')
60 |
61 | negate = Setting(0)
62 |
63 | def __init__(self):
64 | super().__init__()
65 |
66 | geom = QApplication.desktop().availableGeometry()
67 | self.setGeometry(QRect(round(geom.width() * 0.05),
68 | round(geom.height() * 0.05),
69 | round(min(geom.width() * 0.98, self.MAX_WIDTH)),
70 | round(min(geom.height() * 0.95, self.MAX_HEIGHT))))
71 |
72 | self.setMaximumHeight(self.geometry().height())
73 | self.setMaximumWidth(self.geometry().width())
74 |
75 | gui.separator(self.controlArea)
76 |
77 | button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")
78 |
79 | button = gui.button(button_box, self, "Read Surface", callback=self.read_surface)
80 | button.setFixedHeight(45)
81 |
82 | button = gui.button(button_box, self, "Render Surface", callback=self.render_surface)
83 | button.setFixedHeight(45)
84 |
85 | input_box_l = oasysgui.widgetBox(self.controlArea, "Input", addSpace=True, orientation="vertical", height=self.TABS_AREA_HEIGHT)
86 |
87 | box = oasysgui.widgetBox(input_box_l, "", addSpace=False, orientation="horizontal")
88 |
89 | self.le_surface_file_name = oasysgui.lineEdit(box, self, "surface_file_name", "Surface File Name",
90 | labelWidth=120, valueType=str, orientation="horizontal")
91 |
92 | gui.button(box, self, "...", callback=self.selectSurfaceFile)
93 |
94 | gui.comboBox(input_box_l, self, "negate", label="Invert Surface", labelWidth=350,
95 | items=["No", "Yes"], sendSelectedValue=False, orientation="horizontal")
96 |
97 | self.figure = Figure(figsize=(600, 600))
98 | self.figure.patch.set_facecolor('white')
99 |
100 | self.axis = self.figure.add_subplot(111, projection='3d')
101 |
102 | self.axis.set_zlabel("Z [m]")
103 |
104 | self.figure_canvas = FigureCanvas3D(ax=self.axis, fig=self.figure)
105 |
106 | self.mainArea.layout().addWidget(self.figure_canvas)
107 |
108 | gui.rubber(self.mainArea)
109 |
110 | def read_surface(self):
111 | try:
112 | self.surface_file_name = congruence.checkDir(self.surface_file_name)
113 |
114 | xx, yy, zz = OU.read_surface_file(self.surface_file_name)
115 | zz = zz if self.negate==0 else -1.0*zz
116 |
117 | self.xx = xx
118 | self.yy = yy
119 | self.zz = zz
120 |
121 | self.send("Surface Data", OasysSurfaceData(xx=self.xx, yy=self.yy, zz=self.zz, surface_data_file=self.surface_file_name))
122 | except Exception as exception:
123 | QMessageBox.critical(self, "Error",
124 | exception.args[0],
125 | QMessageBox.Ok)
126 |
127 | if self.IS_DEVELOP: raise exception
128 |
129 | def render_surface(self):
130 | try:
131 | self.surface_file_name = congruence.checkDir(self.surface_file_name)
132 |
133 | xx, yy, zz = OU.read_surface_file(self.surface_file_name)
134 | zz = zz if self.negate==0 else -1.0*zz
135 |
136 | self.xx = xx
137 | self.yy = yy
138 | self.zz = zz
139 |
140 | self.axis.clear()
141 |
142 | x_to_plot, y_to_plot = numpy.meshgrid(self.xx, self.yy)
143 |
144 | self.axis.plot_surface(x_to_plot, y_to_plot, zz,
145 | rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True)
146 |
147 | self.axis.set_xlabel("X [m]")
148 | self.axis.set_ylabel("Y [m]")
149 | self.axis.set_zlabel("Z [m]")
150 | self.axis.mouse_init()
151 |
152 | self.figure_canvas.draw()
153 |
154 | self.send("Surface Data", OasysSurfaceData(xx=self.xx, yy=self.yy, zz=self.zz, surface_data_file=self.surface_file_name))
155 |
156 | except Exception as exception:
157 | QMessageBox.critical(self, "Error",
158 | exception.args[0],
159 | QMessageBox.Ok)
160 |
161 | if self.IS_DEVELOP: raise exception
162 |
163 | def selectSurfaceFile(self):
164 | self.le_surface_file_name.setText(oasysgui.selectFileFromDialog(self, self.surface_file_name, "Select Input File", file_extension_filter="HDF5 Files (*.hdf5 *.h5 *.hdf)"))
165 |
166 |
167 |
--------------------------------------------------------------------------------
/scripts/macos/build-macos-app.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | echo
3 | set -e
4 |
5 | usage() {
6 | echo 'usage: build-macos-app.sh [--python-version VER] [--pip-arg ARG] APPPATH
7 | Create (build) an macOS application bundle
8 |
9 | Options:
10 | --python-version VERSION
11 | Python version to install in the application bundle (default: 3.7.5)
12 |
13 | --pip-arg ARG
14 | Pip install arguments to populate the python environemnt in the
15 | application bundle. Can be used multiple times.
16 | If not supplied then by default the latest PyPi published Orange3 is
17 | used.
18 |
19 | -h|--help
20 | Print this help
21 |
22 | Examples
23 | build-macos-app.sh ~/Applications/Oasys1.2.app
24 | Build the application using the latest published version on pypi
25 |
26 | build-macos-app.sh --pip-arg={Oasys1.2==3.3.12,PyQt5} ~/Applications/Oasys1.2.app
27 | Build the application using the specified Orange version
28 |
29 | build-macos-app.sh --pip-arg=path-tolocal-checkout ~/Applications/Oasys1.2-Dev.app
30 | Build the application using a local source checkout
31 |
32 | build-macos-app.sh --pip-arg={-e,path-tolocal-checkout} ~/Applications/Oasys1.2-Dev.app
33 | Build the application and install orange in editable mode
34 |
35 | buils-macos-app.sh --pip-arg={-r,requirements.txt} /Applications/Oasys1.2.app
36 | Build the application using a fixed set of locked requirements.
37 | '
38 | }
39 |
40 | DIR=$(dirname "$0")
41 |
42 | # Python version in the bundled framework
43 | PYTHON_VERSION=3.8.10
44 |
45 | # Pip arguments used to populate the python environment in the application
46 | # bundle
47 | PIP_REQ_ARGS=( )
48 |
49 | while [[ "${1:0:1}" == "-" ]]; do
50 | case "${1}" in
51 | --python-version=*)
52 | PYTHON_VERSION=${1#*=}
53 | shift 1;;
54 | --python-version)
55 | PYTHON_VERSION=${2:?"--python-version requires an argument"}
56 | shift 2;;
57 | --pip-arg=*)
58 | PIP_REQ_ARGS+=( "${1#*=}" )
59 | shift 1;;
60 | --pip-arg)
61 | PIP_REQ_ARGS+=( "${2:?"--pip-arg requires an argument"}" )
62 | shift 2;;
63 | --help|-h)
64 | usage; exit 0;;
65 | -*)
66 | echo "Invalid argument ${1}" >&2; usage >&2; exit 1;;
67 | esac
68 | done
69 |
70 | APPDIR=${1:?"Target APPDIR argument is missing"}
71 |
72 | PYVER=${PYTHON_VERSION%.*} # Major.Minor
73 |
74 | if [[ ${#PIP_REQ_ARGS[@]} -eq 0 ]]; then
75 | PIP_REQ_ARGS+=('numpy~=1.23.2' 'fabio==0.14.0' 'PyQt5==5.15.2' 'PyQtWebEngine~=5.15' 'xraylib~=4.1.2' 'oasys1')
76 | fi
77 |
78 | mkdir -p "${APPDIR}"/Contents/MacOS
79 | mkdir -p "${APPDIR}"/Contents/Frameworks
80 | mkdir -p "${APPDIR}"/Contents/Resources
81 |
82 | cp -R ./lib "${APPDIR}"/Contents/Frameworks
83 |
84 | cp -a "${DIR}"/skeleton.app/Contents/{Resources,Info.plist.in} \
85 | "${APPDIR}"/Contents
86 |
87 | # Layout a 'relocatable' python framework in the app directory
88 | "${DIR}"/python-framework.sh \
89 | --version "${PYTHON_VERSION}" \
90 | --macos 10.9 \
91 | --install-certifi \
92 | "${APPDIR}"/Contents/Frameworks
93 |
94 | ln -fs ../Frameworks/Python.framework/Versions/${PYVER}/Resources/Python.app/Contents/MacOS/Python \
95 | "${APPDIR}"/Contents/MacOS/PythonApp
96 |
97 | ln -fs ../Frameworks/Python.framework/Versions/${PYVER}/bin/python${PYVER} \
98 | "${APPDIR}"/Contents/MacOS/python
99 |
100 | "${APPDIR}"/Contents/MacOS/python -m ensurepip
101 | "${APPDIR}"/Contents/MacOS/python -m pip install pip~=22.2.0 wheel
102 |
103 |
104 | cat <<'EOF' > "${APPDIR}"/Contents/MacOS/ENV
105 |
106 | # Create an environment for running python from the bundle
107 | # Should be run as "source ENV"
108 |
109 | BUNDLE_DIR=`dirname "$0"`/../
110 | BUNDLE_DIR=`perl -MCwd=realpath -e 'print realpath($ARGV[0])' "$BUNDLE_DIR"`/
111 | FRAMEWORKS_DIR="$BUNDLE_DIR"Frameworks/
112 | RESOURCES_DIR="$BUNDLE_DIR"Resources/
113 |
114 | PYVERSION="3.8"
115 | PYTHONEXECUTABLE="$FRAMEWORKS_DIR"Python.framework/Resources/Python.app/Contents/MacOS/Python
116 | PYTHONHOME="$FRAMEWORKS_DIR"Python.framework/Versions/"$PYVERSION"/
117 | DYLD_FRAMEWORK_PATH="$FRAMEWORKS_DIR"${DYLD_FRAMEWORK_PATH:+:$DYLD_FRAMEWORK_PATH}
118 |
119 | export PYTHONNOUSERSITE=1
120 |
121 | # Some non framework libraries are put in $FRAMEWORKS_DIR by machlib standalone
122 | base_ver=11.0
123 | ver=$(sw_vers | grep ProductVersion | cut -d':' -f2 | tr -d ' ')
124 | if [ $(echo -e $base_ver"\n"$ver | sort -V | tail -1) == "$base_ver" ]
125 | then
126 | export DYLD_LIBRARY_PATH="$FRAMEWORKS_DIR"${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}lib/os10
127 | else
128 | export DYLD_LIBRARY_PATH="$FRAMEWORKS_DIR"${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}lib/os11
129 | fi
130 | EOF
131 |
132 | cat <<'EOF' > "${APPDIR}"/Contents/MacOS/Oasys1
133 | #!/bin/bash
134 |
135 | DIR=$(dirname "$0")
136 | source "$DIR"/ENV
137 |
138 | # LaunchServices passes the Carbon process identifier to the application with
139 | # -psn parameter - we do not want it
140 | if [[ "${1}" == -psn_* ]]; then
141 | shift 1
142 | fi
143 |
144 | # Disable user site packages
145 | export PYTHONNOUSERSITE=1
146 |
147 | exec "${DIR}"/PythonApp -m oasys.canvas --force-discovery "$@"
148 | EOF
149 | chmod +x "${APPDIR}"/Contents/MacOS/Oasys1
150 |
151 | cat <<'EOF' > "${APPDIR}"/Contents/MacOS/pip
152 | #!/bin/bash
153 |
154 | DIR=$(dirname "$0")
155 |
156 | # Disable user site packages
157 | export PYTHONNOUSERSITE=1
158 |
159 | exec -a "$0" "${DIR}"/python -m pip "$@"
160 | EOF
161 | chmod +x "${APPDIR}"/Contents/MacOS/pip
162 |
163 | PYTHON="${APPDIR}"/Contents/MacOS/python
164 |
165 | "${PYTHON}" -m pip install --no-warn-script-location "${PIP_REQ_ARGS[@]}"
166 |
167 | VERSION=$("${PYTHON}" -m pip show oasys1 | grep -E '^Version:' |
168 | cut -d " " -f 2)
169 |
170 | m4 -D__VERSION__="${VERSION:?}" "${APPDIR}"/Contents/Info.plist.in \
171 | > "${APPDIR}"/Contents/Info.plist
172 | rm "${APPDIR}"/Contents/Info.plist.in
173 |
174 | # Sanity check
175 | (
176 | # run from an empty dir to avoid importing/finding any packages on ./
177 | tempdir=$(mktemp -d)
178 | cleanup() { rm -r "${tempdir}"; }
179 | trap cleanup EXIT
180 | cd "${tempdir}"
181 | "${PYTHON}" -m pip install --no-cache-dir --no-index oasys1 PyQt5==5.15.2
182 | "${PYTHON}" -m oasys.canvas --help > /dev/null
183 | )
184 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python3
2 |
3 | from importlib.machinery import SourceFileLoader
4 | import os
5 | import subprocess
6 | import platform
7 |
8 | from setuptools import setup
9 |
10 | NAME = 'OASYS1'
11 |
12 | VERSION = '1.2.150'
13 |
14 | ISRELEASED = True
15 |
16 | DESCRIPTION = 'OrAnge SYnchrotron Suite'
17 | README_FILE = os.path.join(os.path.dirname(__file__), 'README.md')
18 | LONG_DESCRIPTION = open(README_FILE).read()
19 | AUTHOR = 'Luca Rebuffi, Manuel Sanchez del Rio and Bioinformatics Laboratory, FRI UL'
20 | AUTHOR_EMAIL = 'lrebuffi@anl.gov'
21 | URL = 'https://github.com/oasys-kit/OASYS1'
22 | DOWNLOAD_URL = 'https://github.com/oasys-kit/OASYS1'
23 | MAINTAINER = 'Luca Rebuffi, Argonne National Lab, USA'
24 | MAINTAINER_EMAIL = 'lrebuffi@anl.gov'
25 | LICENSE = 'GPLv3'
26 |
27 | KEYWORDS = (
28 | 'ray tracing',
29 | 'simulation',
30 | )
31 |
32 | CLASSIFIERS = (
33 | 'Development Status :: 5 - Production/Stable',
34 | 'Environment :: X11 Applications :: Qt',
35 | 'Environment :: Console',
36 | 'Environment :: Plugins',
37 | 'Programming Language :: Python :: 3',
38 | 'License :: OSI Approved :: '
39 | 'GNU General Public License v3 or later (GPLv3+)',
40 | 'Operating System :: POSIX',
41 | 'Operating System :: Microsoft :: Windows',
42 | 'Topic :: Scientific/Engineering :: Visualization',
43 | 'Topic :: Software Development :: Libraries :: Python Modules',
44 | 'Intended Audience :: Education',
45 | 'Intended Audience :: Science/Research',
46 | 'Intended Audience :: Developers',
47 | )
48 |
49 | INSTALL_REQUIRES = (
50 | 'setuptools',
51 | 'requests',
52 | "importlib_resources",
53 | "importlib_metadata",
54 | 'numpy<1.23,>=1.21',
55 | 'fabio==0.11.0',
56 | 'PyQt5==5.15.2',
57 | 'scipy<=1.9.1,>=1.7.3',
58 | 'matplotlib<=3.5.3,>=3.3.2',
59 | 'oasys-canvas-core>=1.0.9',
60 | 'oasys-widget-core>=1.0.5',
61 | 'silx==0.15.0',
62 | 'hdf5plugin',
63 | 'srxraylib>=1.0.28',
64 | 'syned>=1.0.28',
65 | 'wofry>=1.0.31',
66 | )
67 |
68 |
69 | try:
70 | system, node, release, version, machine, processor = platform.uname()
71 | if "Debian 3" in version:
72 | l1 = list(INSTALL_REQUIRES)
73 | for i,element in enumerate(l1):
74 | if "PyQt5" in element:
75 | l1[i] = "PyQt5==5.11.3"
76 | INSTALL_REQUIRES = tuple(l1)
77 | except:
78 | pass
79 |
80 |
81 | SETUP_REQUIRES = (
82 | 'setuptools',
83 | )
84 |
85 | # Return the git revision as a string
86 | def git_version():
87 | """Return the git revision as a string.
88 |
89 | Copied from numpy setup.py
90 | """
91 | def _minimal_ext_cmd(cmd):
92 | # construct minimal environment
93 | env = {}
94 | for k in ['SYSTEMROOT', 'PATH']:
95 | ver = os.environ.get(k)
96 | if ver is not None:
97 | env[k] = ver
98 | # LANGUAGE is used on win32
99 | env['LANGUAGE'] = 'C'
100 | env['LANG'] = 'C'
101 | env['LC_ALL'] = 'C'
102 | out = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env).communicate()[0]
103 | return out
104 |
105 | try:
106 | out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
107 | git_revision = out.strip().decode('ascii')
108 | except OSError:
109 | git_revision = "Unknown"
110 |
111 | return git_revision
112 |
113 |
114 | def write_version_py(filename='oasys/version.py'):
115 | # Copied from numpy setup.py
116 | cnt = """
117 | # THIS FILE IS GENERATED FROM OASYS SETUP.PY
118 | short_version = '%(version)s'
119 | version = '%(version)s'
120 | full_version = '%(full_version)s'
121 | git_revision = '%(git_revision)s'
122 | release = %(isrelease)s
123 |
124 | if not release:
125 | version = full_version
126 | short_version += ".dev"
127 | """
128 | full_version = VERSION
129 | if os.path.exists('.git'):
130 | git_revision = git_version()
131 | elif os.path.exists('oasys/version.py'):
132 | # must be a source distribution, use existing version file
133 | version = SourceFileLoader('oasys.version', 'oasys/version.py').load_module()
134 | git_revision = version.git_revision
135 | else:
136 | git_revision = "Unknown"
137 |
138 | if not ISRELEASED:
139 | full_version += '.dev0+' + git_revision[:7]
140 |
141 | with open(filename, 'w') as file:
142 | file.write(cnt % {'version': VERSION,
143 | 'full_version': full_version,
144 | 'git_revision': git_revision,
145 | 'isrelease': str(ISRELEASED)})
146 |
147 | PACKAGES = (
148 | "oasys",
149 | "oasys.canvas",
150 | "oasys.canvas.styles",
151 | "oasys.menus",
152 | "oasys.widgets",
153 | "oasys.widgets.tools",
154 | "oasys.widgets.loop_management",
155 | )
156 |
157 | PACKAGE_DATA = {
158 | "oasys.application": ["data/*.txt"],
159 | "oasys.canvas": ["icons/*.png", "icons/*.svg"],
160 | "oasys.canvas.styles": ["*.qss", "orange/*.svg"],
161 | "oasys.widgets.tools": ["icons/*.png", "icons/*.svg", "misc/*.png"],
162 | "oasys.widgets.loop_management": ["icons/*.png", "icons/*.svg"],
163 | "oasys.widgets.scanning": ["icons/*.png", "icons/*.svg"],
164 | }
165 |
166 | ENTRY_POINTS = {
167 | 'oasys.widgets' : (
168 | "Oasys Tools = oasys.widgets.tools",
169 | "Oasys Basic Loops = oasys.widgets.loop_management",
170 | "Oasys Scanning Loops = oasys.widgets.scanning",
171 | )
172 | }
173 |
174 | def setup_package():
175 | write_version_py()
176 | setup(
177 | name=NAME,
178 | version=VERSION,
179 | description=DESCRIPTION,
180 | long_description=LONG_DESCRIPTION,
181 | author=AUTHOR,
182 | author_email=AUTHOR_EMAIL,
183 | maintainer=MAINTAINER,
184 | maintainer_email=MAINTAINER_EMAIL,
185 | url=URL,
186 | download_url=DOWNLOAD_URL,
187 | license=LICENSE,
188 | keywords=KEYWORDS,
189 | classifiers=CLASSIFIERS,
190 | packages=PACKAGES,
191 | package_data=PACKAGE_DATA,
192 | entry_points=ENTRY_POINTS,
193 | # extra setuptools args
194 | zip_safe=False, # the package can run out of an .egg file
195 | include_package_data=True,
196 | install_requires=INSTALL_REQUIRES,
197 | setup_requires=SETUP_REQUIRES,
198 | )
199 |
200 | if __name__ == '__main__':
201 | setup_package()
202 |
--------------------------------------------------------------------------------
/oasys/widgets/abstract/scanning/abstract_scan_file_node_point.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # #########################################################################
4 | # Copyright (c) 2020, UChicago Argonne, LLC. All rights reserved. #
5 | # #
6 | # Copyright 2020. UChicago Argonne, LLC. This software was produced #
7 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National #
8 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the #
9 | # U.S. Department of Energy. The U.S. Government has rights to use, #
10 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR #
11 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR #
12 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is #
13 | # modified to produce derivative works, such modified software should #
14 | # be clearly marked, so as not to confuse it with the version available #
15 | # from ANL. #
16 | # #
17 | # Additionally, redistribution and use in source and binary forms, with #
18 | # or without modification, are permitted provided that the following #
19 | # conditions are met: #
20 | # #
21 | # * Redistributions of source code must retain the above copyright #
22 | # notice, this list of conditions and the following disclaimer. #
23 | # #
24 | # * Redistributions in binary form must reproduce the above copyright #
25 | # notice, this list of conditions and the following disclaimer in #
26 | # the documentation and/or other materials provided with the #
27 | # distribution. #
28 | # #
29 | # * Neither the name of UChicago Argonne, LLC, Argonne National #
30 | # Laboratory, ANL, the U.S. Government, nor the names of its #
31 | # contributors may be used to endorse or promote products derived #
32 | # from this software without specific prior written permission. #
33 | # #
34 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS #
35 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #
36 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS #
37 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago #
38 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
39 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #
40 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #
41 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
42 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT #
43 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #
44 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
45 | # POSSIBILITY OF SUCH DAMAGE. #
46 | # #########################################################################
47 |
48 | from PyQt5.QtWidgets import QFileDialog
49 |
50 | from orangewidget import gui
51 | from orangewidget.settings import Setting
52 |
53 | from oasys.widgets import gui as oasysgui
54 |
55 | from oasys.widgets.abstract.scanning.abstract_scan_node_point import AbstractScanLoopPoint
56 |
57 | from oasys.util.oasys_util import TriggerIn
58 |
59 | class AbstractScanFileLoopPoint(AbstractScanLoopPoint):
60 | inputs = [("Trigger", TriggerIn, "passTrigger"),
61 | ("Files", list, "setFiles")]
62 |
63 | files_area = None
64 | variable_files = Setting([""])
65 |
66 | def create_specific_loop_box(self, box):
67 | box_files = oasysgui.widgetBox(box, "", addSpace=False, orientation="vertical", height=270)
68 |
69 | gui.button(box_files, self, "Select Height Error Profile Data Files", callback=self.select_files)
70 |
71 | self.files_area = oasysgui.textArea(height=200, width=360)
72 |
73 | self.refresh_files_text_area()
74 |
75 | box_files.layout().addWidget(self.files_area)
76 |
77 | gui.separator(box)
78 |
79 | def select_files(self):
80 | files, _ = QFileDialog.getOpenFileNames(self,
81 | "Select Height Error Profiles", "", "Data Files (*.dat)",
82 | options=QFileDialog.Options())
83 | if files:
84 | self.variable_files = files
85 |
86 | self.refresh_files_text_area()
87 |
88 | def setFiles(self, files_data):
89 | if not files_data is None:
90 | if isinstance(files_data, str):
91 | self.variable_files.append(files_data)
92 | elif isinstance(files_data, list):
93 | self.variable_files = files_data
94 | else:
95 | raise ValueError("Error Profile Data File: format not recognized")
96 |
97 | self.refresh_files_text_area()
98 |
99 | def refresh_files_text_area(self):
100 | text = ""
101 | for file in self.variable_files:
102 | text += file + "\n"
103 | self.files_area.setText(text)
104 |
105 | self.number_of_new_objects = len(self.variable_files)
106 |
107 | def has_variable_um(self): return False
108 |
109 | def get_current_value_type(self): return str
110 |
111 | def initialize_start_loop(self):
112 | self.current_variable_value = self.variable_files[0]
113 | self.number_of_new_objects = len(self.variable_files)
114 |
115 | self.start_button.setEnabled(False)
116 |
117 | return True
118 |
119 | def keep_looping(self):
120 | if self.current_new_object < self.number_of_new_objects:
121 | if self.current_variable_value is None: self.current_new_object = 1
122 | else: self.current_new_object += 1
123 |
124 | self.current_variable_value = self.variable_files[self.current_new_object - 1]
125 |
126 | return True
127 | else:
128 | return False
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/oasys/canvas/widgetsscheme.py:
--------------------------------------------------------------------------------
1 | """
2 | OASYS Widgets Scheme
3 | ====================
4 |
5 | A Scheme for OASYS Orange Widgets Scheme.
6 |
7 | .. autoclass:: OASYSWidgetsScheme
8 | :bases:
9 |
10 | .. autoclass:: OASYSWidgetsSignalManager
11 | :bases:
12 |
13 | """
14 | import os
15 | import sys
16 | import logging
17 |
18 | import sip
19 |
20 | from PyQt5.QtCore import QSettings
21 | from PyQt5.QtCore import pyqtSignal as Signal, pyqtProperty as Property
22 |
23 | from orangecanvas.scheme import Scheme, readwrite
24 |
25 | from orangewidget.canvas.workflow import (
26 | WidgetsScheme, WidgetManager, WidgetsSignalManager
27 | )
28 |
29 | log = logging.getLogger(__name__)
30 |
31 |
32 | def check_working_directory(working_directory):
33 | if sys.platform == "win32": return working_directory.replace("/", "\\") # weird bug since 12/2023
34 | else: return working_directory.replace("\\", "/")
35 |
36 | class OASYSWidgetsScheme(WidgetsScheme):
37 | #: Signal emitted when the working directory changes.
38 | working_directory_changed = Signal(str)
39 | workspace_units_changed = Signal(int)
40 |
41 | def __init__(self, parent=None, title=None, description=None, working_directory=None, workspace_units=None):
42 | self.__canvas_main_window = parent
43 |
44 | settings = QSettings()
45 |
46 | self.__working_directory = (working_directory or settings.value("output/default-working-directory", os.path.expanduser("~/Oasys"), type=str))
47 | self.__working_directory = check_working_directory(self.__working_directory)
48 | if not os.path.exists(self.__working_directory): os.makedirs(self.__working_directory, exist_ok=True)
49 |
50 | self.__workspace_units = (workspace_units or settings.value("output/default-units", 1, type=int))
51 |
52 | super().__init__(parent, title=title, description=description)
53 |
54 | # Replace the signal manager from.
55 | self.signal_manager.setParent(None)
56 | self.signal_manager.deleteLater()
57 | sip.delete(self.signal_manager)
58 | sip.delete(self.widget_manager)
59 |
60 | self.set_loop_flags(Scheme.AllowLoops)
61 | self.signal_manager = OASYSSignalManager(self)
62 | self.widget_manager = OASYSWidgetManager()
63 | self.widget_manager.set_scheme(self)
64 |
65 | def set_working_directory(self, working_directory):
66 | """
67 | Set the scheme working_directory.
68 | """
69 | working_directory = check_working_directory(working_directory)
70 |
71 | if self.__working_directory != working_directory:
72 | self.__working_directory = working_directory
73 | self.working_directory_changed.emit(working_directory)
74 |
75 | def working_directory(self):
76 | """
77 | The working_directory of the scheme.
78 | """
79 | return self.__working_directory
80 |
81 | def set_workspace_units(self, units):
82 | """
83 | Set the scheme units.
84 | """
85 | if self.__workspace_units != units:
86 | self.__workspace_units = units
87 | self.workspace_units_changed.emit(units)
88 |
89 | def workspace_units(self):
90 | """
91 | The units of the scheme.
92 | """
93 | return self.__workspace_units
94 |
95 | def canvas_main_window(self):
96 | return self.__canvas_main_window
97 |
98 | working_directory = Property(str,
99 | fget=working_directory,
100 | fset=set_working_directory)
101 |
102 | workspace_units = Property(str,
103 | fget=workspace_units,
104 | fset=set_workspace_units)
105 |
106 | canvas_main_window = Property(object,
107 | fget=canvas_main_window)
108 |
109 |
110 | def save_to(self, stream, pretty=True, pickle_fallback=False):
111 | """
112 | Reimplemented from Scheme.save_to.
113 | """
114 | if isinstance(stream, str):
115 | stream = open(stream, "wb")
116 |
117 | self.sync_node_properties()
118 |
119 | tree = readwrite.scheme_to_etree(self, pickle_fallback=pickle_fallback)
120 | root = tree.getroot()
121 | root.set("working_directory", self.working_directory or "")
122 | root.set("workspace_units", str(self.workspace_units) or "")
123 |
124 | if pretty: readwrite.indent(tree.getroot(), 0)
125 |
126 | if sys.version_info < (2, 7):
127 | # in Python 2.6 the write does not have xml_declaration parameter.
128 | tree.write(stream, encoding="utf-8")
129 | else:
130 | tree.write(stream, encoding="utf-8", xml_declaration=True)
131 |
132 |
133 | class OASYSWidgetManager(WidgetManager):
134 | def set_scheme(self, scheme):
135 | super().set_scheme(scheme)
136 | scheme.working_directory_changed.connect(self.__working_directory_changed)
137 | scheme.workspace_units_changed.connect(self.__workspace_units_changed)
138 |
139 | def create_widget_instance(self, node):
140 | """
141 | Reimplemented from WidgetManager.create_widget_instance
142 | """
143 | widget = super().create_widget_instance(node)
144 | if hasattr(widget, "setWorkingDirectory"): widget.setWorkingDirectory(self.scheme().working_directory)
145 | if hasattr(widget, "setWorkspaceUnits"): widget.setWorkspaceUnits(self.scheme().workspace_units)
146 | if hasattr(widget, "setCanvasMainWindow"): widget.setCanvasMainWindow(self.scheme().canvas_main_window)
147 | if hasattr(widget, "createdFromNode"): widget.createdFromNode(node)
148 |
149 | return widget
150 |
151 | def __working_directory_changed(self, workdir):
152 | for node in self.scheme().nodes:
153 | w = self.widget_for_node(node)
154 | if hasattr(w, "setWorkingDirectory"):
155 | w.setWorkingDirectory(workdir)
156 |
157 | def __workspace_units_changed(self, units):
158 | for node in self.scheme().nodes:
159 | w = self.widget_for_node(node)
160 | if hasattr(w, "setWorkspaceUnits"):
161 | w.setWorkspaceUnits(units)
162 |
163 | class OASYSSignalManager(WidgetsSignalManager):
164 | def pending_nodes(self):
165 | """
166 | Reimplemented from SignalManager.pending_nodes.
167 |
168 | Enforce some custom ordering semantics in workflow cycles.
169 | """
170 |
171 | pending = super().pending_nodes()
172 |
173 | pending_new = [node for node in pending
174 | if not getattr(self.scheme().widget_for_node(node),
175 | "process_last", False)]
176 |
177 | if pending_new:
178 | pending = pending_new
179 |
180 | return pending
181 |
--------------------------------------------------------------------------------
/oasys/widgets/widget.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from PyQt5.QtWidgets import QScrollArea
4 | from PyQt5.QtCore import Qt
5 | from PyQt5.Qt import QIcon
6 |
7 | from orangewidget import widget
8 |
9 | def layout_insert(layout, widget, before):
10 | for i in range(layout.count()):
11 | item = layout.itemAt(i)
12 | if item.widget() is before:
13 | break
14 | else:
15 | raise ValueError("{} is not in layout".format(widget))
16 | layout.insertWidget(i, widget, )
17 |
18 | class OWWidget(widget.OWWidget):
19 |
20 | IS_DEVELOP = False if not "OASYSDEVELOP" in os.environ.keys() else str(os.environ.get('OASYSDEVELOP')) == "1"
21 |
22 | def __init__(self):
23 | super().__init__()
24 |
25 | self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint)
26 |
27 | def getScene(self):
28 | return self.canvas_main_window.current_document().scene()
29 |
30 | def getNode(self):
31 | if self._node is None: self._node = self.getScene().node_for_item(self._node_item)
32 | return self._node
33 |
34 | def getNodeItem(self):
35 | if self._node_item is None: self._node_item = self.getScene().item_for_node(self._node)
36 | return self._node_item
37 |
38 | def changeNodeIcon(self, icon):
39 | node_item = self.getNodeItem()
40 | if not node_item is None:
41 | node_item.icon_item.hide()
42 | if isinstance(icon, QIcon): node_item.setIcon(icon)
43 | else: node_item.setIcon(QIcon(icon))
44 | node_item.update()
45 |
46 | def changeNodeTitle(self, title):
47 | node_item = self.getNodeItem()
48 | if not node_item is None:
49 | node_item.setTitle(title)
50 | node_item.update()
51 |
52 | def insertLayout(self):
53 | """
54 | Reimplemented from OWWidget.insertLayout.
55 |
56 | Pull the OWWidget created controlArea and mainArea widgets into
57 | QScrollArea's.
58 |
59 | """
60 | super().insertLayout()
61 |
62 | self.setStyleSheet("background-color: #EBEBEB;")
63 |
64 | cls = type(self)
65 |
66 | if cls.want_basic_layout and cls.want_control_area:
67 | layout = self.leftWidgetPart.layout()
68 | area = QScrollArea()
69 | layout_insert(layout, area, before=self.controlArea)
70 | layout.takeAt(layout.indexOf(self.controlArea))
71 | area.setWidget(self.controlArea)
72 | area.setWidgetResizable(True)
73 |
74 | if cls.want_basic_layout and cls.want_main_area:
75 | layout = self.topWidgetPart.layout()
76 | area = QScrollArea()
77 | layout_insert(layout, area, before=self.mainArea)
78 | layout.takeAt(layout.indexOf(self.mainArea))
79 | area.setWidget(self.mainArea)
80 | area.setWidgetResizable(True)
81 |
82 | def setCanvasMainWindow(self, canvas_main_window):
83 | self.canvas_main_window = canvas_main_window
84 |
85 | def setWorkingDirectory(self, directory):
86 | self.working_directory = directory
87 |
88 | self.after_change_working_directory()
89 |
90 | def setWorkspaceUnits(self, units):
91 | self.workspace_units = units
92 |
93 | if self.workspace_units == 0:
94 | self.workspace_units_label = "m"
95 | self.workspace_units_to_m = 1.0
96 | self.workspace_units_to_cm = 100.0
97 | self.workspace_units_to_mm = 1000.0
98 |
99 | elif self.workspace_units == 1:
100 | self.workspace_units_label = "cm"
101 | self.workspace_units_to_m = 0.01
102 | self.workspace_units_to_cm = 1.0
103 | self.workspace_units_to_mm = 10.0
104 |
105 | elif self.workspace_units == 2:
106 | self.workspace_units_label = "mm"
107 | self.workspace_units_to_m = 0.001
108 | self.workspace_units_to_cm = 0.1
109 | self.workspace_units_to_mm = 1.0
110 |
111 | self.after_change_workspace_units()
112 |
113 | def after_change_working_directory(self):
114 | pass
115 |
116 | def after_change_workspace_units(self):
117 | pass
118 |
119 | def __setattr__(self, name, value):
120 | super().__setattr__(name, value)
121 |
122 | for shower in getattr(self, "showers", []):
123 | if name in shower.expression:
124 | shower()
125 |
126 | def show_at(self, expression, what):
127 | class ShowerClass:
128 | def __init__(shower):
129 | shower.what = what
130 | shower.expression = expression
131 |
132 | def __call__(shower):
133 | x = self # to force self into the closure, because we need it in the expression
134 | to_show = eval(expression)
135 | if shower.what.isHidden() == to_show:
136 | if to_show:
137 | shower.what.show()
138 | else:
139 | shower.what.hide()
140 |
141 | shower = ShowerClass()
142 | if not hasattr(self, "showers"):
143 | self.showers = []
144 | self.showers.append(shower)
145 |
146 | def process_showers(self):
147 | for shower in getattr(self, "showers", []):
148 | shower()
149 |
150 |
151 | # Pull signal definition constants to oasys widget namespace.
152 | Default = widget.Default
153 | NonDefault = widget.NonDefault
154 | Single = widget.Single
155 | Multiple = widget.Multiple
156 | Explicit = widget.Explicit
157 | Dynamic = widget.Dynamic
158 |
159 | InputSignal = widget.InputSignal
160 | OutputSignal = widget.OutputSignal
161 |
162 | from orangewidget import gui
163 | from orangewidget.settings import Setting
164 |
165 | from PyQt5.QtWidgets import QApplication
166 | from PyQt5.QtCore import QRect
167 |
168 | class AutomaticWidget(OWWidget):
169 |
170 | is_automatic_execution = Setting(True)
171 |
172 | CONTROL_AREA_WIDTH = 405
173 |
174 | MAX_WIDTH = 1320
175 | MAX_HEIGHT = 700
176 |
177 | def __init__(self, is_automatic=True):
178 | super().__init__()
179 |
180 | geom = QApplication.desktop().availableGeometry()
181 | self.setGeometry(QRect(round(geom.width()*0.05),
182 | round(geom.height()*0.05),
183 | round(min(geom.width()*0.98, self.MAX_WIDTH)),
184 | round(min(geom.height()*0.95, self.MAX_HEIGHT))))
185 |
186 | self.setMaximumHeight(self.geometry().height())
187 | self.setMaximumWidth(self.geometry().width())
188 |
189 | self.controlArea.setFixedWidth(self.CONTROL_AREA_WIDTH)
190 |
191 | if is_automatic:
192 | self.general_options_box = gui.widgetBox(self.controlArea, "General Options", addSpace=True, orientation="horizontal")
193 |
194 | gui.checkBox(self.general_options_box, self, 'is_automatic_execution', 'Automatic Execution')
195 | else:
196 | self.is_automatic_execution=False
197 |
--------------------------------------------------------------------------------
/oasys/widgets/loop_management/ow_node_point.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from orangewidget.widget import OWAction
4 | from oasys.widgets import widget
5 | from oasys.widgets import gui as oasysgui
6 | from oasys.widgets.gui import ConfirmDialog
7 |
8 | from orangewidget import gui
9 | from PyQt5.QtGui import QFont, QPalette, QColor
10 | from PyQt5.QtWidgets import QMessageBox
11 | from orangewidget.settings import Setting
12 |
13 | from oasys.util.oasys_util import TriggerIn, TriggerOut
14 |
15 | class LoopPoint(widget.OWWidget):
16 |
17 | name = "Loop Point"
18 | description = "Tools: LoopPoint"
19 | icon = "icons/cycle.png"
20 | maintainer = "Luca Rebuffi"
21 | maintainer_email = "lrebuffi(@at@)anl.gov"
22 | priority = 2
23 | category = "User Defined"
24 | keywords = ["data", "file", "load", "read"]
25 |
26 | inputs = [("Trigger", TriggerIn, "passTrigger")]
27 |
28 | outputs = [{"name":"Trigger",
29 | "type":TriggerOut,
30 | "doc":"Trigger",
31 | "id":"Trigger"}]
32 | want_main_area = 0
33 |
34 | number_of_new_objects = Setting(1)
35 | current_new_object = 0
36 | run_loop = True
37 | suspend_loop = False
38 |
39 | #################################
40 | process_last = True
41 | #################################
42 |
43 | def __init__(self):
44 | self.runaction = OWAction("Start", self)
45 | self.runaction.triggered.connect(self.startLoop)
46 | self.addAction(self.runaction)
47 |
48 | self.runaction = OWAction("Stop", self)
49 | self.runaction.triggered.connect(self.stopLoop)
50 | self.addAction(self.runaction)
51 |
52 | self.runaction = OWAction("Suspend", self)
53 | self.runaction.triggered.connect(self.suspendLoop)
54 | self.addAction(self.runaction)
55 |
56 | self.runaction = OWAction("Restart", self)
57 | self.runaction.triggered.connect(self.restartLoop)
58 | self.addAction(self.runaction)
59 |
60 | self.setFixedWidth(400)
61 | self.setFixedHeight(220)
62 |
63 | button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=True, orientation="horizontal")
64 |
65 | self.start_button = gui.button(button_box, self, "Start", callback=self.startLoop)
66 | self.start_button.setFixedHeight(35)
67 |
68 | stop_button = gui.button(button_box, self, "Stop", callback=self.stopLoop)
69 | stop_button.setFixedHeight(35)
70 | font = QFont(stop_button.font())
71 | font.setBold(True)
72 | stop_button.setFont(font)
73 | palette = QPalette(stop_button.palette()) # make a copy of the palette
74 | palette.setColor(QPalette.ButtonText, QColor('red'))
75 | stop_button.setPalette(palette) # assign new palette
76 |
77 | self.stop_button = stop_button
78 |
79 | button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=True, orientation="horizontal")
80 |
81 | suspend_button = gui.button(button_box, self, "Suspend", callback=self.suspendLoop)
82 | suspend_button.setFixedHeight(35)
83 | font = QFont(suspend_button.font())
84 | font.setBold(True)
85 | suspend_button.setFont(font)
86 | palette = QPalette(suspend_button.palette()) # make a copy of the palette
87 | palette.setColor(QPalette.ButtonText, QColor('orange'))
88 | suspend_button.setPalette(palette) # assign new palette
89 |
90 | self.re_start_button = gui.button(button_box, self, "Restart", callback=self.restartLoop)
91 | self.re_start_button.setFixedHeight(35)
92 | self.re_start_button.setEnabled(False)
93 |
94 | left_box_1 = oasysgui.widgetBox(self.controlArea, "Loop Management", addSpace=True, orientation="vertical", width=380, height=100)
95 |
96 | oasysgui.lineEdit(left_box_1, self, "number_of_new_objects", "Number of new " + self.get_object_name() + "s", labelWidth=250, valueType=int, orientation="horizontal")
97 |
98 | self.le_current_new_object = oasysgui.lineEdit(left_box_1, self, "current_new_object", "Current New " + self.get_object_name(), labelWidth=250, valueType=int, orientation="horizontal")
99 | self.le_current_new_object.setReadOnly(True)
100 | font = QFont(self.le_current_new_object.font())
101 | font.setBold(True)
102 | self.le_current_new_object.setFont(font)
103 | palette = QPalette(self.le_current_new_object.palette()) # make a copy of the palette
104 | palette.setColor(QPalette.Text, QColor('dark blue'))
105 | palette.setColor(QPalette.Base, QColor(243, 240, 160))
106 | self.le_current_new_object.setPalette(palette)
107 |
108 | gui.rubber(self.controlArea)
109 |
110 | def startLoop(self):
111 | self.current_new_object = 1
112 | self.start_button.setEnabled(False)
113 | self.setStatusMessage("Running " + self.get_object_name() + " " + str(self.current_new_object) + " of " + str(self.number_of_new_objects))
114 | self.send("Trigger", TriggerOut(new_object=True))
115 |
116 | def stopLoop(self):
117 | if ConfirmDialog.confirmed(parent=self, message="Confirm Interruption of the Loop?"):
118 | self.run_loop = False
119 | self.setStatusMessage("Interrupted by user")
120 |
121 | def suspendLoop(self):
122 | try:
123 | if ConfirmDialog.confirmed(parent=self, message="Confirm Suspension of the Loop?"):
124 | self.run_loop = False
125 | self.suspend_loop = True
126 | self.stop_button.setEnabled(False)
127 | self.re_start_button.setEnabled(True)
128 | self.setStatusMessage("Suspended by user")
129 | except:
130 | pass
131 |
132 | def restartLoop(self):
133 | try:
134 | self.run_loop = True
135 | self.suspend_loop = False
136 | self.stop_button.setEnabled(True)
137 | self.re_start_button.setEnabled(False)
138 | self.passTrigger(TriggerIn(new_object=True))
139 | except:
140 | pass
141 |
142 | def passTrigger(self, trigger):
143 | if self.run_loop:
144 | if trigger:
145 | if trigger.interrupt:
146 | self.current_new_object = 0
147 | self.start_button.setEnabled(True)
148 | self.setStatusMessage("")
149 | self.send("Trigger", TriggerOut(new_object=False))
150 | elif trigger.new_object:
151 | if self.current_new_object == 0:
152 | QMessageBox.critical(self, "Error", "Loop has to be started properly: press the button Start", QMessageBox.Ok)
153 | return
154 |
155 | if self.current_new_object < self.number_of_new_objects:
156 | self.current_new_object += 1
157 | self.setStatusMessage("Running " + self.get_object_name() + " " + str(self.current_new_object) + " of " + str(self.number_of_new_objects))
158 | self.start_button.setEnabled(False)
159 | self.send("Trigger", TriggerOut(new_object=True))
160 | else:
161 | self.current_new_object = 0
162 | self.start_button.setEnabled(True)
163 | self.setStatusMessage("")
164 | self.send("Trigger", TriggerOut(new_object=False))
165 | else:
166 | if not self.suspend_loop:
167 | self.current_new_object = 0
168 | self.start_button.setEnabled(True)
169 |
170 | self.send("Trigger", TriggerOut(new_object=False))
171 | self.setStatusMessage("")
172 | self.run_loop = True
173 | self.suspend_loop = False
174 |
175 | def get_object_name(self):
176 | return "Object"
177 |
178 | from PyQt5.QtWidgets import QApplication
179 |
180 | if __name__ == "__main__":
181 | a = QApplication(sys.argv)
182 | ow = LoopPoint()
183 | ow.show()
184 | a.exec_()
185 | ow.saveSettings()
186 |
--------------------------------------------------------------------------------
/oasys/widgets/abstract/scanning/abstract_scan_variable_node_point.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # #########################################################################
4 | # Copyright (c) 2020, UChicago Argonne, LLC. All rights reserved. #
5 | # #
6 | # Copyright 2020. UChicago Argonne, LLC. This software was produced #
7 | # under U.S. Government contract DE-AC02-06CH11357 for Argonne National #
8 | # Laboratory (ANL), which is operated by UChicago Argonne, LLC for the #
9 | # U.S. Department of Energy. The U.S. Government has rights to use, #
10 | # reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR #
11 | # UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR #
12 | # ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is #
13 | # modified to produce derivative works, such modified software should #
14 | # be clearly marked, so as not to confuse it with the version available #
15 | # from ANL. #
16 | # #
17 | # Additionally, redistribution and use in source and binary forms, with #
18 | # or without modification, are permitted provided that the following #
19 | # conditions are met: #
20 | # #
21 | # * Redistributions of source code must retain the above copyright #
22 | # notice, this list of conditions and the following disclaimer. #
23 | # #
24 | # * Redistributions in binary form must reproduce the above copyright #
25 | # notice, this list of conditions and the following disclaimer in #
26 | # the documentation and/or other materials provided with the #
27 | # distribution. #
28 | # #
29 | # * Neither the name of UChicago Argonne, LLC, Argonne National #
30 | # Laboratory, ANL, the U.S. Government, nor the names of its #
31 | # contributors may be used to endorse or promote products derived #
32 | # from this software without specific prior written permission. #
33 | # #
34 | # THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS #
35 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #
36 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS #
37 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago #
38 | # Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
39 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #
40 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #
41 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
42 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT #
43 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #
44 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
45 | # POSSIBILITY OF SUCH DAMAGE. #
46 | # #########################################################################
47 |
48 | from oasys.widgets import gui as oasysgui
49 |
50 | from orangewidget import gui
51 | from PyQt5.QtGui import QFont, QPalette, QColor
52 | from orangewidget.settings import Setting
53 |
54 | from oasys.widgets.abstract.scanning.abstract_scan_node_point import AbstractScanLoopPoint
55 |
56 | class AbstractScanVariableLoopPoint(AbstractScanLoopPoint):
57 |
58 | variable_value_from = Setting(0.0)
59 | variable_value_to = Setting(0.0)
60 | variable_value_step = Setting(0.0)
61 |
62 | list_of_values = Setting([""])
63 | kind_of_loop = Setting(0)
64 |
65 | def create_specific_loop_box(self, box):
66 | gui.separator(box)
67 |
68 | gui.comboBox(box, self, "kind_of_loop", label="Kind of Loop", labelWidth=350,
69 | items=["From Range", "From List"],
70 | callback=self.set_KindOfLoop, sendSelectedValue=False, orientation="horizontal")
71 |
72 | self.box_1 = oasysgui.widgetBox(box, "", addSpace=False, orientation="vertical", width=360, height=160)
73 | self.box_2 = oasysgui.widgetBox(box, "", addSpace=False, orientation="vertical", width=360, height=160)
74 |
75 | oasysgui.lineEdit(self.box_1, self, "variable_value_from", "Value From", labelWidth=250, valueType=float, orientation="horizontal", callback=self.calculate_step)
76 | oasysgui.lineEdit(self.box_1, self, "variable_value_to", "Value to", labelWidth=250, valueType=float, orientation="horizontal", callback=self.calculate_step)
77 | oasysgui.lineEdit(self.box_1, self, "number_of_new_objects", "Number of Steps", labelWidth=250, valueType=int, orientation="horizontal", callback=self.calculate_step)
78 |
79 | self.list_of_values_ta = oasysgui.textArea(height=150, width=360, readOnly=False)
80 | self.list_of_values_ta.textChanged.connect(self.list_of_values_ta_changed)
81 |
82 | text = ""
83 | for value in self.list_of_values:
84 | text += value + "\n"
85 |
86 | self.list_of_values_ta.setText(text[:-1])
87 | self.box_2.layout().addWidget(self.list_of_values_ta)
88 |
89 | self.le_variable_value_step = oasysgui.lineEdit(self.box_1, self, "variable_value_step", "Step Value", labelWidth=250, valueType=float, orientation="horizontal")
90 | self.le_variable_value_step.setReadOnly(True)
91 | font = QFont(self.le_variable_value_step.font())
92 | font.setBold(True)
93 | self.le_variable_value_step.setFont(font)
94 | palette = QPalette(self.le_variable_value_step.palette()) # make a copy of the palette
95 | palette.setColor(QPalette.Text, QColor('dark blue'))
96 | palette.setColor(QPalette.Base, QColor(243, 240, 160))
97 | self.le_variable_value_step.setPalette(palette)
98 |
99 | self.set_KindOfLoop()
100 | self.calculate_step()
101 |
102 | gui.separator(box)
103 |
104 | def list_of_values_ta_changed(self):
105 | self.list_of_values = []
106 |
107 | values = self.list_of_values_ta.toPlainText().split("\n")
108 | for value in values:
109 | if not value.strip() == "": self.list_of_values.append(value)
110 |
111 | if self.kind_of_loop==1: self.number_of_new_objects = len(self.list_of_values)
112 |
113 | if len(self.list_of_values) == 0: self.list_of_values.append("")
114 |
115 | def set_KindOfLoop(self):
116 | self.box_1.setVisible(self.kind_of_loop == 0)
117 | self.box_2.setVisible(self.kind_of_loop == 1)
118 |
119 | def calculate_step(self):
120 | try: self.variable_value_step = round((self.variable_value_to - self.variable_value_from) / self.number_of_new_objects, 8)
121 | except: self.variable_value_step = 0.0
122 |
123 | def get_current_value_type(self): return float
124 |
125 | def initialize_start_loop(self):
126 | do_loop = True
127 |
128 | if self.kind_of_loop == 0:
129 | self.current_variable_value = round(self.variable_value_from, 8)
130 | self.calculate_step()
131 | elif len(self.list_of_values) > 0:
132 | self.current_variable_value = self.list_of_values[self.current_new_object - 1]
133 | else:
134 | do_loop = False
135 |
136 | return do_loop
137 |
138 | def keep_looping(self):
139 | if (self.current_new_object < self.number_of_new_objects) or (self.current_new_object == self.number_of_new_objects and self.kind_of_loop==0):
140 | if self.current_variable_value is None:
141 | self.current_new_object = 1
142 |
143 | if self.kind_of_loop == 0:
144 | self.current_variable_value = round(self.variable_value_from, 8)
145 | self.calculate_step()
146 | elif len(self.list_of_values) > 0:
147 | self.current_variable_value = self.list_of_values[self.current_new_object - 1]
148 | else:
149 | self.current_new_object += 1
150 | if self.kind_of_loop == 0:
151 | self.current_variable_value = round(self.current_variable_value + self.variable_value_step, 8)
152 | elif len(self.list_of_values) > 0:
153 | self.current_variable_value = self.list_of_values[self.current_new_object - 1]
154 | return True
155 | else:
156 | return False
157 |
--------------------------------------------------------------------------------
/oasys/widgets/tools/ow_surface_file_merger.py:
--------------------------------------------------------------------------------
1 | import os, sys
2 |
3 | import numpy
4 | from PyQt5.QtCore import QRect, Qt
5 | from PyQt5.QtWidgets import QApplication, QMessageBox, QLabel, QSizePolicy
6 | from PyQt5.QtGui import QTextCursor, QFont, QPalette, QColor, QPixmap
7 |
8 | from matplotlib import cm
9 | from oasys.widgets.gui import FigureCanvas3D
10 | from matplotlib.figure import Figure
11 |
12 | from orangewidget import gui, widget
13 | from orangewidget.settings import Setting
14 |
15 | from oasys.widgets.widget import OWWidget
16 | from oasys.widgets import gui as oasysgui
17 | from oasys.widgets import congruence
18 |
19 | from oasys.util.oasys_objects import OasysPreProcessorData, OasysErrorProfileData, OasysSurfaceData
20 |
21 | import oasys.util.oasys_util as OU
22 |
23 | try:
24 | from mpl_toolkits.mplot3d import Axes3D # necessario per caricare i plot 3D
25 | except:
26 | pass
27 |
28 | class OWSurfaceFileReader(OWWidget):
29 | name = "Surface File Merger"
30 | id = "surface_file_merger"
31 | description = "Surface File Merger"
32 | icon = "icons/surface_merger.png"
33 | author = "Luca Rebuffi"
34 | maintainer_email = "lrebuffi@anl.gov"
35 | priority = 5
36 | category = ""
37 | keywords = ["surface_file_mberger"]
38 |
39 | inputs = [("Surface Data #1", object, "set_input_1"),
40 | ("Surface Data #2", object, "set_input_2"),
41 | ]
42 |
43 | outputs = [{"name": "PreProcessor_Data",
44 | "type": OasysPreProcessorData,
45 | "doc": "PreProcessor Data",
46 | "id": "PreProcessor_Data"},
47 | {"name": "Surface_Data",
48 | "type": OasysSurfaceData,
49 | "doc": "Surface Data",
50 | "id": "Surface_Data"}]
51 |
52 |
53 | want_main_area = 1
54 | want_control_area = 1
55 |
56 | MAX_WIDTH = 1320
57 | MAX_HEIGHT = 700
58 |
59 | IMAGE_WIDTH = 860
60 | IMAGE_HEIGHT = 645
61 |
62 | CONTROL_AREA_WIDTH = 405
63 | TABS_AREA_HEIGHT = 618
64 |
65 | xx = None
66 | yy = None
67 | zz = None
68 |
69 | xx_1 = None
70 | yy_1 = None
71 | zz_1 = None
72 |
73 | xx_2 = None
74 | yy_2 = None
75 | zz_2 = None
76 |
77 | surface_data = None
78 | preprocessor_data = None
79 |
80 | surface_file_name = Setting('merged_surface.hdf5')
81 |
82 | def __init__(self):
83 | super().__init__()
84 |
85 | geom = QApplication.desktop().availableGeometry()
86 | self.setGeometry(QRect(round(geom.width() * 0.05),
87 | round(geom.height() * 0.05),
88 | round(min(geom.width() * 0.98, self.MAX_WIDTH)),
89 | round(min(geom.height() * 0.95, self.MAX_HEIGHT))))
90 |
91 | self.setMaximumHeight(self.geometry().height())
92 | self.setMaximumWidth(self.geometry().width())
93 |
94 | gui.separator(self.controlArea)
95 |
96 | button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")
97 |
98 | button = gui.button(button_box, self, "Read Surface", callback=self.read_surface)
99 | button.setFixedHeight(45)
100 |
101 | button = gui.button(button_box, self, "Render Surface", callback=self.render_surface)
102 | button.setFixedHeight(45)
103 |
104 | input_box_l = oasysgui.widgetBox(self.controlArea, "Input", addSpace=True, orientation="horizontal", height=self.TABS_AREA_HEIGHT)
105 |
106 | self.le_surface_file_name = oasysgui.lineEdit(input_box_l, self, "surface_file_name", "Surface File Name",
107 | labelWidth=120, valueType=str, orientation="horizontal")
108 |
109 | gui.button(input_box_l, self, "...", callback=self.selectSurfaceFile)
110 |
111 |
112 | self.figure = Figure(figsize=(600, 600))
113 | self.figure.patch.set_facecolor('white')
114 |
115 | self.axis = self.figure.add_subplot(111, projection='3d')
116 |
117 | self.axis.set_zlabel("Z [m]")
118 |
119 | self.figure_canvas = FigureCanvas3D(ax=self.axis, fig=self.figure)
120 |
121 | self.mainArea.layout().addWidget(self.figure_canvas)
122 |
123 | gui.rubber(self.mainArea)
124 |
125 |
126 | def set_input_1(self, data):
127 | if not data is None:
128 | if isinstance(data, OasysPreProcessorData):
129 | self.xx_1 = data.error_profile_data.surface_data.xx
130 | self.yy_1 = data.error_profile_data.surface_data.yy
131 | self.zz_1 = data.error_profile_data.surface_data.zz
132 | elif isinstance(data, OasysSurfaceData):
133 | self.xx_1 = data.xx
134 | self.yy_1 = data.yy
135 | self.zz_1 = data.zz
136 | else:
137 | QMessageBox.critical(self, "Error",
138 | "Data Type #1 not recognized",
139 | QMessageBox.Ok)
140 |
141 | def set_input_2(self, data):
142 | if not data is None:
143 | if isinstance(data, OasysPreProcessorData):
144 | self.xx_2 = data.error_profile_data.surface_data.xx
145 | self.yy_2 = data.error_profile_data.surface_data.yy
146 | self.zz_2 = data.error_profile_data.surface_data.zz
147 | elif isinstance(data, OasysSurfaceData):
148 | self.xx_2 = data.xx
149 | self.yy_2 = data.yy
150 | self.zz_2 = data.zz
151 | else:
152 | QMessageBox.critical(self, "Error",
153 | "Data Type #2 not recognized",
154 | QMessageBox.Ok)
155 |
156 | def compute(self, plot_data=False):
157 | try:
158 | if not self.xx_1 is None and not self.xx_2 is None:
159 | xx_1 = self.xx_1
160 | yy_1 = self.yy_1
161 | zz_1 = self.zz_1
162 |
163 | xx_2 = self.xx_2
164 | yy_2 = self.yy_2
165 | zz_2 = self.zz_2
166 |
167 | if not (len(xx_1) == len(xx_2) and
168 | len(yy_1) == len(yy_1) and
169 | round(xx_1[0], 6) == round(xx_2[0], 6) and
170 | round(xx_1[-1], 6) == round(xx_2[-1], 6) and
171 | round(yy_1[0], 6) == round(yy_2[0], 6) and
172 | round(yy_1[-1], 6) == round(yy_2[-1], 6)):
173 | raise ValueError("The two surfaces cannot be merged: dimensions or binning incompatible")
174 |
175 | xx = xx_2
176 | yy = yy_2
177 | zz = zz_2 + zz_1
178 |
179 | self.axis.clear()
180 |
181 | x_to_plot, y_to_plot = numpy.meshgrid(xx, yy)
182 |
183 | if plot_data:
184 | self.axis.plot_surface(x_to_plot, y_to_plot, zz,
185 | rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True)
186 |
187 | self.axis.set_xlabel("X [m]")
188 | self.axis.set_ylabel("Y [m]")
189 | self.axis.set_zlabel("Z [m]")
190 | self.axis.mouse_init()
191 |
192 | self.figure_canvas.draw()
193 |
194 | if not (self.surface_file_name.endswith("hd5") or self.surface_file_name.endswith("hdf5") or self.surface_file_name.endswith("hdf")):
195 | self.surface_file_name += ".hdf5"
196 |
197 | OU.write_surface_file(zz, xx, yy, self.surface_file_name)
198 |
199 | error_profile_x_dim = abs(xx[-1] - xx[0])
200 | error_profile_y_dim = abs(yy[-1] - yy[0])
201 |
202 |
203 | self.send("PreProcessor_Data", OasysPreProcessorData(error_profile_data=OasysErrorProfileData(surface_data=OasysSurfaceData(xx=xx,
204 | yy=yy,
205 | zz=zz,
206 | surface_data_file=self.surface_file_name),
207 | error_profile_x_dim=error_profile_x_dim,
208 | error_profile_y_dim=error_profile_y_dim)))
209 | self.send("Surface_Data", OasysSurfaceData(xx=xx,
210 | yy=yy,
211 | zz=zz,
212 | surface_data_file=self.surface_file_name))
213 |
214 | except Exception as exception:
215 | QMessageBox.critical(self, "Error",
216 | exception.args[0],
217 | QMessageBox.Ok)
218 |
219 | if self.IS_DEVELOP: raise exception
220 |
221 |
222 | def read_surface(self):
223 | self.compute(plot_data=False)
224 |
225 | def render_surface(self):
226 | self.compute(plot_data=True)
227 |
228 | def selectSurfaceFile(self):
229 | self.le_surface_file_name.setText(oasysgui.selectFileFromDialog(self, self.surface_file_name, "Select Input File", file_extension_filter="HDF5 Files (*.hdf5)"))
230 |
231 |
232 |
--------------------------------------------------------------------------------
/oasys/canvas/icons/orange-canvas.svg:
--------------------------------------------------------------------------------
1 |
2 |
58 |
--------------------------------------------------------------------------------
/oasys/canvas/styles/orange.qss:
--------------------------------------------------------------------------------
1 | /* Default Orange stylesheet
2 | */
3 |
4 | /*
5 | * Icon search paths relative to this files directory.
6 | * (main.py script will add this to QDir.searchPaths)
7 | */
8 |
9 | @canvas_icons: orange;
10 |
11 |
12 | /* Main window background color */
13 |
14 | CanvasMainWindow {
15 | background-color: #E9EFF2;
16 | }
17 |
18 | QMainWindow::separator {
19 | width: 1px; /* when vertical */
20 | height: 1px; /* when horizontal */
21 | }
22 |
23 |
24 | /* The widget buttons in the dock tool box */
25 |
26 | WidgetsToolGrid QToolButton {
27 | font-family: "Helvetica";
28 | font-size: 10px;
29 | font-weight: bold;
30 | color: #333;
31 | }
32 |
33 |
34 | /* Dock widget toolbox tab buttons (categories) */
35 |
36 | WidgetToolBox QToolButton#toolbox-tab-button {
37 | /* nativeStyling property overrides the QStyle and uses a fixed drawing
38 | routine */
39 | qproperty-nativeStyling_: "false";
40 |
41 | font-family: "Helvetica";
42 | font-size: 14px;
43 | font-weight: bold;
44 | color: #333;
45 | border: none;
46 | border-bottom: 1px solid #B5B8B8;
47 | background: qlineargradient(
48 | x1: 0, y1: 0, x2: 0, y2: 1,
49 | stop: 0 #F2F2F2,
50 | stop: 0.5 #F2F2F2,
51 | stop: 0.8 #EBEBEB,
52 | stop: 1.0 #DBDBDB
53 | );
54 | }
55 |
56 |
57 | WidgetToolBox QToolButton#toolbox-tab-button:hover {
58 | background-color: palette(light);
59 | }
60 |
61 |
62 | WidgetToolBox QToolButton#toolbox-tab-button:checked {
63 | background-color: palette(dark);
64 | }
65 |
66 |
67 | WidgetToolBox QToolButton#toolbox-tab-button:focus {
68 | background-color: palette(highlight);
69 | border: 1px solid #609ED7
70 | }
71 |
72 |
73 | WidgetToolBox ToolGrid {
74 | background-color: #F2F2F2;
75 | padding-bottom: 8px;
76 | }
77 |
78 |
79 | WidgetToolBox ToolGrid QToolButton {
80 | border: none;
81 | /* border-bottom: 2px solid #B5B8B8;
82 | border-right: 2px solid #B5B8B8; */
83 | background-color: #F2F2F2;
84 | border-radius: 8px;
85 | }
86 |
87 |
88 | WidgetToolBox ToolGrid QToolButton[last-column] {
89 | border-right: none;
90 | }
91 |
92 | WidgetToolBox ToolGrid QToolButton:focus {
93 | background-color: palette(window);
94 | }
95 |
96 | WidgetToolBox ToolGrid QToolButton:hover {
97 | background-color: palette(light);
98 | }
99 |
100 | WidgetToolBox ToolGrid QToolButton:pressed {
101 | background-color: palette(dark);
102 | }
103 |
104 |
105 | /* QuickCategoryToolbar popup menus */
106 |
107 | CategoryPopupMenu {
108 | background-color: #E9EFF2;
109 | }
110 |
111 | CategoryPopupMenu ToolTree QTreeView::item {
112 | height: 25px;
113 | border-bottom: 1px solid #e9eff2;
114 | }
115 |
116 | CategoryPopupMenu QTreeView::item:selected {
117 | background: qlineargradient(
118 | x1: 0, y1: 0, x2: 0, y2: 1,
119 | stop: 0 #688EF6,
120 | stop: 0.5 #4047f4,
121 | stop: 1.0 #2D68F3
122 | );
123 | color: white;
124 | }
125 |
126 |
127 | /* Canvas Dock Header */
128 |
129 | CollapsibleDockWidget::title {
130 | background: qlineargradient(
131 | x1: 0, y1: 0, x2: 0, y2: 1,
132 | stop: 0 #808080, stop: 1.0 #666
133 | );
134 | }
135 |
136 | /* Dock widget title bar button icons (icon size for both must be set).
137 | * The buttons define the title bar height.
138 | */
139 |
140 | CollapsibleDockWidget::close-button, CollapsibleDockWidget::float-button {
141 | padding: 1px;
142 | icon-size: 11px;
143 | }
144 |
145 | CanvasToolDock WidgetToolBox {
146 | border: 1px solid #B5B8B8;
147 | }
148 |
149 |
150 | /* Toolbar at the bottom of the dock widget when in in expanded state
151 | */
152 |
153 | CanvasToolDock QToolBar {
154 | height: 28;
155 | spacing: 1;
156 | border: none;
157 | /*
158 | background: qlineargradient(
159 | x1: 0, y1: 0, x2: 0, y2: 1,
160 | stop: 0 #808080, stop: 1.0 #666
161 | );
162 | */
163 | background-color: #898989;
164 |
165 | }
166 |
167 | CanvasToolDock QToolBar QToolButton {
168 | border: none;
169 | background: qlineargradient(
170 | x1: 0, y1: 0, x2: 0, y2: 1,
171 | stop: 0 #808080, stop: 1.0 #666
172 | );
173 | }
174 |
175 | CanvasToolDock QToolBar QToolButton:menu-indicator {
176 | image: url(canvas_icons:/Dropdown.svg);
177 | subcontrol-position: top right;
178 | height: 8px;
179 | width: 8px;
180 | }
181 |
182 | CanvasToolDock QToolBar QToolButton:checked,
183 | CanvasToolDock QToolBar QToolButton:pressed {
184 | background-color: #FFA840;
185 | }
186 |
187 |
188 | /* Toolbar in the dock when in collapsed state.
189 | */
190 |
191 | CollapsibleDockWidget QWidget#canvas-quick-dock QToolBar {
192 | spacing: 1;
193 | border: none;
194 | /*
195 | background: qlineargradient(
196 | x1: 0, y1: 0, x2: 0, y2: 1,
197 | stop: 0 #808080, stop: 1.0 #666
198 | );
199 | */
200 | background-color: #898989;
201 | }
202 |
203 |
204 | CollapsibleDockWidget QWidget#canvas-quick-dock QToolBar QToolButton {
205 | border: none;
206 | background: qlineargradient(
207 | x1: 0, y1: 0, x2: 1, y2: 0,
208 | stop: 0 #808080, stop: 1.0 #666
209 | );
210 | }
211 |
212 | CollapsibleDockWidget QWidget#canvas-quick-dock QToolBar QToolButton:menu-indicator {
213 | image: url(canvas_icons:/Dropdown.svg);
214 | subcontrol-position: top right;
215 | height: 8px;
216 | width: 8px;
217 | }
218 |
219 | CollapsibleDockWidget QWidget#canvas-quick-dock QToolBar QToolButton:checked,
220 | CollapsibleDockWidget QWidget#canvas-quick-dock QToolBar QToolButton:pressed {
221 | background-color: #FFA840;
222 | }
223 |
224 |
225 | /* Splitter between the widget toolbox and quick help.
226 | */
227 |
228 | CanvasToolDock QSplitter::handle {
229 | border: 1px solid #B5B8B8;
230 |
231 | /* border-top: 1px solid #B5B8B8;
232 | * border-bottom: 1px solid #B5B8B8;
233 | * border-left: 1px solid #B6B6B6;
234 | * border-right: 1px solid #B6B6B6;
235 | */
236 |
237 | background: qlineargradient(
238 | x1: 0, y1: 0, x2: 0, y2: 1,
239 | stop: 0 #D4D4D4, stop: 0.05 #EDEDED,
240 | stop: 0.5 #F2F2F2,
241 | stop: 0.95 #EDEDED, stop: 1.0 #E0E0E0
242 | );
243 | }
244 |
245 |
246 | /* Scheme Info Dialog
247 | */
248 |
249 | SchemeInfoDialog {
250 | font-family: "Helvetica";
251 | background-color: #E9EFF2;
252 | }
253 |
254 | SchemeInfoDialog SchemeInfoEdit QLabel {
255 | font-family: "Helvetica";
256 | font-weight: bold;
257 | font-size: 16px;
258 | color: black;
259 | }
260 |
261 | SchemeInfoDialog QLabel#heading {
262 | font-size: 21px;
263 | color: #515151;
264 | }
265 |
266 | SchemeInfoDialog StyledWidget#auto-show-container * {
267 | font-family: "Helvetica";
268 | font-size: 12px;
269 | color: #1A1A1A;
270 | }
271 |
272 | SchemeInfoDialog StyledWidget#auto-show-container {
273 | border-top: 1px solid #C1C2C3;
274 | }
275 |
276 | SchemeInfoDialog SchemeInfoEdit QLineEdit {
277 | padding: 4px;
278 | /* background-color: red; */
279 | /* font-weight: normal; */
280 | font-size: 12px;
281 | color: #1A1A1A;
282 | }
283 |
284 | SchemeInfoDialog SchemeInfoEdit QTextEdit {
285 | padding: 4px;
286 | background-color: white;
287 | /* font-weight: normal; */
288 | font-size: 12px;
289 | color: #1A1A1A;
290 | }
291 |
292 |
293 | /* Preview Dialog (Recent Schemes and Tutorials)
294 | */
295 |
296 | PreviewDialog {
297 | background-color: #E9EFF2;
298 | }
299 |
300 | PreviewDialog QLabel#heading {
301 | font-family: "Helvetica";
302 | font-weight: bold;
303 | font-size: 21px;
304 | color: #515151;
305 | }
306 |
307 | PreviewDialog PreviewBrowser * {
308 | font-family: "Helvetica";
309 | color: #1A1A1A;
310 | }
311 |
312 | PreviewDialog PreviewBrowser TextLabel#path-text {
313 | font-size: 12px;
314 | }
315 |
316 | PreviewDialog PreviewBrowser QLabel#path-label {
317 | font-size: 12px;
318 | }
319 |
320 | PreviewDialog DropShadowFrame {
321 | qproperty-radius_: 10;
322 | qproperty-color_: rgb(0, 0, 0, 100);
323 | }
324 |
325 | /* Welcome Screen Dialog
326 | */
327 |
328 | WelcomeDialog {
329 | background-color: #E9EFF2;
330 | }
331 |
332 | WelcomeDialog QToolButton {
333 | font-family: "Helvetica";
334 | font-size: 13px;
335 | font-style: normal;
336 | font-weight: bold;
337 | color: #333;
338 | }
339 |
340 | WelcomeDialog QWidget#bottom-bar {
341 | border-top: 1px solid #C1C2C3;
342 | }
343 |
344 | WelcomeDialog QWidget#bottom-bar QCheckBox {
345 | font-family: "Helvetica";
346 | font-size: 12px;
347 | color: #333;
348 | }
349 |
350 | /* SchemeEditWidget
351 | */
352 |
353 | SchemeEditWidget {
354 | font-family: "Helvetica";
355 | font-size: 12px;
356 | }
357 |
358 | /* Quick Menu
359 | */
360 |
361 | QuickMenu {
362 | background-color: #E9EFF2;
363 | }
364 |
365 | QuickMenu QFrame#menu-frame {
366 | border: 1px solid #9CACB4;
367 | border-radius: 3px;
368 | background-color: #E9EFF2;
369 | }
370 |
371 | QuickMenu QTreeView::item {
372 | border-bottom: 1px solid #e9eff2;
373 | }
374 |
375 | QuickMenu QTreeView::item:selected {
376 | background: qlineargradient(
377 | x1: 0, y1: 0, x2: 0, y2: 1,
378 | stop: 0 #688EF6,
379 | stop: 0.5 #4047f4,
380 | stop: 1.0 #2D68F3
381 | );
382 | color: white;
383 | }
384 |
385 | QuickMenu TabBarWidget QToolButton {
386 | height: 25px;
387 | border-bottom: 1px solid palette(dark);
388 | padding-right: 5px;
389 | padding-left: 5px;
390 | qproperty-showMenuIndicator_: true;
391 | }
392 |
393 | QuickMenu TabBarWidget QToolButton#search-tab-button {
394 | background-color: #9CACB4;
395 | }
396 |
397 | QuickMenu TabBarWidget QToolButton:menu-indicator {
398 | image: url(canvas_icons:/arrow-right.svg);
399 | subcontrol-position: center right;
400 | height: 8px;
401 | width: 8px;
402 | }
403 |
404 | /* Quick Menu search line edit
405 | */
406 |
407 | QuickMenu QLineEdit {
408 | height: 25px;
409 | margin: 0px;
410 | padding: 0px;
411 | border: 1px solid #9CACB4;
412 | border-radius: 3px;
413 | background-color: white;
414 | }
415 |
416 | QuickMenu QLineEdit:focus {
417 | border: 2px solid #9CACB4;
418 | border-radius: 2px;
419 | }
420 |
421 | QuickMenu QLineEdit QToolButton {
422 | qproperty-flat_: false;
423 | height: 25px;
424 | border: 1px solid #9CACB4;
425 | border-top-left-radius: 3px;
426 | border-bottom-left-radius: 3px;
427 | background-color: #9CACB4;
428 | padding: 0px;
429 | margin: 0px;
430 | icon-size: 23px;
431 | }
432 |
--------------------------------------------------------------------------------
/scripts/macos/python-framework.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | usage() {
4 | echo "$0 [ --version VERSION ] FRAMEWORKPATH
5 |
6 | Fetch, extract and layout a macOS relocatable Python framework at FRAMEWORKPATH
7 |
8 | Options:
9 | --version VERSION Python version (default ${VERSION})
10 | --macos MACOSVER Minimum supported macOS version (as of 3.6.5 and
11 | 3.7.0 the python.org provides binaries for 10.6
12 | and 10.9 macOS versions; default ${MACOSVER})
13 | --install-certifi If present then certifi pypi package will be
14 | installed and its cert store linked in
15 | \${PREFIX}/etc/openssl
16 | -v --verbose Increase verbosity level
17 |
18 | Note:
19 | Python >= 3.6 comes with a bundled openssl library build that is
20 | configured to load certificates from
21 | /Library/Frameworks/Python.frameworks/\${pyver}/etc/openssl
22 |
23 | This script will patch python's stdlib ssl.py to add a
24 | \${PREFIX}/etc/openssl/cert.pem (where \${PREFIX} is the runtime prefix)
25 | certificate store to the default verification chain. However it will only
26 | supply the file if the --install-certifi parameter is passed
27 |
28 | Example
29 | -------
30 | $ python-framework.sh ./
31 | $ Python.framework/Versions/3.5/bin/python3.5 --version
32 | $ python-framework.sh --version 2.7.12 ./2.7
33 | $ ./2.7/Python.framework/Versions/2.7/bin/python2.7 --version
34 | "
35 | }
36 |
37 |
38 | VERSION=3.7.5
39 | MACOSVER=10.9
40 | VERBOSE_LEVEL=0
41 | INSTALL_CERTIFI=
42 |
43 |
44 | verbose() {
45 | local level=${1:?}
46 | shift 1
47 | if [[ ${VERBOSE_LEVEL:-0} -ge ${level} ]]; then
48 | echo "$@"
49 | fi
50 | }
51 |
52 | python-framework-fetch-pkg() {
53 | local cachedir=${1:?}
54 | local version=${2:?}
55 | local macosver=${3:-10.6}
56 | local versiondir=${version%%[abrpc]*} # strip alpha, beta, rc component
57 | local filename=python-${version}-macosx${macosver}.pkg
58 | local url="https://www.python.org/ftp/python/${versiondir}/${filename}"
59 |
60 | echo ${url}
61 |
62 | mkdir -p "${cachedir}"
63 | if [[ -f "${cachedir}/${filename}" ]]; then
64 | verbose 1 "python-${version}-macosx{macosver}.pkg is present in cache"
65 | return 0
66 | fi
67 | local tmpfile=$(mktemp "${cachedir}/${filename}"-XXXX)
68 | cleanup-on-exit() {
69 | if [ -f "${tmpfile}" ]; then
70 | rm "${tmpfile}"
71 | fi
72 | }
73 |
74 | (
75 | trap cleanup-on-exit EXIT
76 | verbose 1 "Fetching ${url}"
77 | curl -sSL --fail -o "${tmpfile}" "${url}"
78 | mv "${tmpfile}" "${cachedir}/${filename}"
79 | )
80 | }
81 |
82 |
83 | python-framework-extract-pkg() {
84 | local targetdir=${1:?}
85 | local pkgpath=${2:?}
86 | local pkgfilename
87 | pkgfilename=$(basename "${pkgpath}")
88 | mkdir -p "${targetdir}"/Python.framework
89 | verbose 1 "Extracting framework at ${targetdir}/Python.framework"
90 | (
91 | tmpdir=$(mktemp -d -t python-framework-extract-pkg)
92 | cleanup-on-exit() {
93 | if [ -d "${tmpdir:?}" ] ; then
94 | rm -rf "${tmpdir:?}"
95 | fi
96 | }
97 | trap cleanup-on-exit EXIT
98 | pkgutil --expand "${pkgpath}" "${tmpdir:?}/${pkgfilename}" || exit 1
99 | tar -C "${targetdir}"/Python.framework \
100 | -xf "${tmpdir}/${pkgfilename}/Python_Framework.pkg/Payload" || exit 1
101 | )
102 | }
103 |
104 |
105 | python-framework-relocate() {
106 | local fmkdir=${1:?}
107 | if [[ ! ${fmkdir} =~ .*/Python.framework ]]; then
108 | echo "${fmkdir} is not a Python.framework" >&2
109 | return 1
110 | fi
111 |
112 | shopt -s nullglob
113 | local versions=( "${fmkdir}"/Versions/?.? )
114 | shopt -u nullglob
115 |
116 | if [[ ! ${#versions[*]} == 1 ]]; then
117 | echo "Single version framework expected (found: ${versions[@]})"
118 | return 2
119 | fi
120 | local ver_short=${versions##*/}
121 | local prefix="${fmkdir}"/Versions/${ver_short}
122 | local bindir="${prefix}"/bin
123 | local libdir="${prefix}"/lib
124 |
125 | local existingid=$(otool -X -D "${prefix}"/Python | tail -n 1)
126 | local anchor="${existingid%%/Python.framework*}"
127 |
128 | if [[ ! ${anchor} =~ /.* ]]; then
129 | echo "${anchor} is not an absolute path" 2>&1
130 | return 2
131 | fi
132 |
133 | chmod +w "${fmkdir}"/Versions/${ver_short}/Python
134 | # change main lib's install id
135 | install_name_tool \
136 | -id @rpath/Python.framework/Versions/${ver_short}/Python \
137 | "${fmkdir}"/Versions/${ver_short}/Python
138 |
139 | # Add the containing frameworks path to rpath
140 | install_name_tool \
141 | -add_rpath @loader_path/../../../ \
142 | "${fmkdir}"/Versions/${ver_short}/Python
143 |
144 | # all expected executable binaries
145 | local binnames=( python${ver_short} python${ver_short}-32 \
146 | pythonw${ver_short} pythonw${ver_short}-32 \
147 | python${ver_short}m )
148 |
149 | for binname in "${binnames[@]}";
150 | do
151 | if [ -f "${bindir}/${binname}" ]; then
152 | install_name_tool \
153 | -change "${anchor}"/Python.framework/Versions/${ver_short}/Python \
154 | "@executable_path/../Python" \
155 | "${bindir}/${binname}"
156 | fi
157 | done
158 |
159 | install_name_tool \
160 | -change "${anchor}"/Python.framework/Versions/${ver_short}/Python \
161 | "@executable_path/../../../../Python" \
162 | "${prefix}"/Resources/Python.app/Contents/MacOS/Python
163 |
164 | for lib in libncursesw libmenuw libformw libpanelw libssl libcrypto;
165 | do
166 | local libpath="${libdir}"/${lib}.dylib
167 | if [[ -f "${libpath}" ]]; then
168 | local libid=$(otool -X -D "${libpath}")
169 | local libbasename=$(basename "${libid}")
170 |
171 | chmod +w "${libpath}"
172 | install_name_tool \
173 | -id @rpath/Python.framework/Versions/${ver_short}/lib/${libbasename} \
174 | "$libpath"
175 |
176 | local librefs=( $(otool -X -L "${libpath}" | cut -d " " -f 1) )
177 | for libref in "${librefs[@]}"
178 | do
179 | if [[ ${libref} =~ ${anchor}/Python.framework/.* ]]; then
180 | local libbasename=$(basename "${libref}")
181 | install_name_tool \
182 | -change "${libref}" @loader_path/${libbasename} \
183 | "${libpath}"
184 |
185 | fi
186 | done
187 | fi
188 | done
189 |
190 | local dylibdir="${libdir}"/python${ver_short}/lib-dynload
191 | # _curses.so, _curses_panel.so, readline.so, ...
192 | local solibs=( "${dylibdir}"/*.so )
193 | for libpath in "${solibs[@]}"
194 | do
195 | local librefs=( $(otool -X -L "${libpath}" | cut -d " " -f 1) )
196 | for libref in "${librefs[@]}"
197 | do
198 | local strip_prefix="${anchor}"/Python.framework
199 | local strip_prefixn=$(( ${#strip_prefix} + 1 ))
200 | if [[ ${libref} =~ ${strip_prefix}/.* ]]; then
201 | local relpath=$(echo "${libref}" | cut -c $(( ${strip_prefixn} + 1))- )
202 | # TODO: should @loader_path be preferred here?
203 | install_name_tool \
204 | -change "${libref}" \
205 | @rpath/Python.framework/"${relpath}" \
206 | "${libpath}"
207 | fi
208 | done
209 | done
210 |
211 | # files/modules which reference /Library/Frameworks/Python.framework/
212 | # - bin/*
213 | # - lib/pkgconfig/*.pc
214 | # - lib/python3.5/_sysconfigdata.py
215 | # - lib/python3.5/config-3.5m/python-config.py
216 |
217 | sed -i.bck s@prefix=${anchor}'.*'@prefix=\${pcfiledir}/../..@ \
218 | "${libdir}"/pkgconfig/python-${ver_short}.pc
219 |
220 | # 3.6.* has bundled libssl with a hardcoded absolute openssl_{cafile,capath}
221 | # (need to set SSL_CERT_FILE environment var in all scripts?
222 | # or patch ssl.py module to add certs to default verify list?)
223 | if [[ ${ver_short#*.} -ge 6 ]]; then
224 | patch-ssl "${prefix}"
225 | fi
226 | }
227 |
228 |
229 | # patch python 3.6 to add etc/openssl/cert.pem cert store located relative
230 | # to the runtime prefix.
231 | patch-ssl() {
232 | local prefix=${1:?}
233 | # lib/python relative to prefix
234 | local pylibdir=$(
235 | cd "${prefix}";
236 | shopt -s failglob;
237 | local path=( lib/python?.? )
238 | echo "${path:?}"
239 | )
240 |
241 | patch "${prefix}/${pylibdir}"/ssl.py - <&2
300 | usage >&2; exit 1;;
301 | esac
302 | done
303 |
304 | python-framework-fetch-pkg ~/.cache/pkgs/ ${VERSION} ${MACOSVER}
305 | python-framework-extract-pkg \
306 | "${1:?"FRAMEWORKPATH argument is missing"}" \
307 | ~/.cache/pkgs/python-${VERSION}-macosx${MACOSVER}.pkg
308 |
309 | python-framework-relocate "${1:?}"/Python.framework
310 |
311 | # Update the Versions/Current symlink
312 | (
313 | cd "${1:?}"/Python.framework/Versions
314 | shopt -s failglob
315 | ln -shf ?.? ./Current # assuming single version framework
316 | )
317 |
318 | if [[ ${INSTALL_CERTIFI} ]]; then
319 | verbose 1 "Installing and linking certifi pypi package"
320 | install-certifi "${1:?}"/Python.framework/Versions/Current
321 | fi
322 |
--------------------------------------------------------------------------------