Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Create easily installable packages of FORCE tools #37

Merged
merged 60 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
4ac252d
Adding some scripts to make a cx_Freeze package.
joshua-cogliati-inl Dec 12, 2023
a002a6e
Adding support for a heron command.
joshua-cogliati-inl Dec 19, 2023
15ae2ad
On windows, the code to get this in setup.py was segfaulting.
joshua-cogliati-inl Dec 21, 2023
70d5129
modifications for mac build
j-bryan Jan 19, 2024
e2dc396
basic working GUI; has a hard time redirecting HERON and RAVEN print …
j-bryan Jan 25, 2024
ee8a95e
simplify to only support running functions, not scripts
j-bryan Jan 25, 2024
35040f4
Attempt at finding ipopt.
joshua-cogliati-inl Feb 1, 2024
ed0b2ab
Fixing bug.
joshua-cogliati-inl Feb 2, 2024
38da25a
refactoring of GUI into MVC paradigm
j-bryan Feb 2, 2024
5495be4
fixes status panel updates
j-bryan Feb 2, 2024
a300dc1
GUI for running raven and heron
j-bryan Feb 2, 2024
b6e3f66
fixes ctrl+c command to close window
j-bryan Feb 2, 2024
98ee262
working example with ipopt
j-bryan Feb 7, 2024
167d624
Merge branch 'gui' into installation
j-bryan Feb 8, 2024
d773e6f
Merge branch 'finding_ipopt' into installation
j-bryan Feb 8, 2024
f3df54d
OS handling in setup; general cleanup
j-bryan Feb 8, 2024
78d09aa
driver for TEAL
j-bryan Feb 8, 2024
64b24a1
Initial inno file.
joshua-cogliati-inl Feb 13, 2024
90c0cc7
Adding raven and heron icons.
joshua-cogliati-inl Feb 13, 2024
c92287f
Adding icons for heron and raven.
joshua-cogliati-inl Feb 13, 2024
c61cd34
adds TEAL standalone with GUI
j-bryan Feb 13, 2024
3b5d87b
Merge remote-tracking branch 'origin/main' into inno_work
joshua-cogliati-inl Feb 13, 2024
78eb22a
rework of file input specification
j-bryan Feb 14, 2024
920177c
fixes input file spec handling for raven_framework
j-bryan Feb 14, 2024
1de277d
Adding teal icon.
joshua-cogliati-inl Feb 14, 2024
9b877b5
Merge remote-tracking branch 'j-bryan/teal' into inno_work
joshua-cogliati-inl Feb 14, 2024
7437180
Adding TEAL to inno file.
joshua-cogliati-inl Feb 15, 2024
5ba00da
Adding script directory so raven runs raven works.
joshua-cogliati-inl Feb 20, 2024
13e03c5
Removing including ipopt in setup.py
joshua-cogliati-inl Feb 20, 2024
db6718f
better CLI argument handling and default directory for file browsers
j-bryan Feb 20, 2024
1a3c742
handles HERON input schema definition option
j-bryan Mar 4, 2024
2285dff
CLI argument handling and some package inclusion fixes
j-bryan Mar 4, 2024
25f1d85
remove status panel
j-bryan Mar 4, 2024
150860d
speed up text widget update with threading
j-bryan Mar 5, 2024
651c832
fix for file location persistence not saving correctly
j-bryan Mar 5, 2024
96e2300
include imageio plugins
j-bryan Mar 14, 2024
ffb2745
FORCE build script
j-bryan Apr 29, 2024
95daedc
documentation build script
j-bryan Apr 29, 2024
e3bbed8
adds examples and docs to build directory
j-bryan May 1, 2024
350b691
install Workbench after installing FORCE
j-bryan May 15, 2024
6dd0afa
install Workbench after running FORCE installer
j-bryan May 20, 2024
38bcf6f
configuring workbench for heron by default
j-bryan Jun 3, 2024
c5a5ca1
open Workbench from HERON launcher
j-bryan Jun 10, 2024
a91046f
build script for mac
j-bryan Jun 18, 2024
b6eff91
build mac FORCE app with applescript launcher
j-bryan Jun 24, 2024
57b0895
adding correct force icon
j-bryan Jun 24, 2024
06a588d
mac build tweaks
j-bryan Jul 1, 2024
5e567a1
GUI updates and finding Workbench
j-bryan Jul 3, 2024
11b25c5
better utilities for finding workbench installation
j-bryan Jul 25, 2024
424661d
heron file windows registry fix
j-bryan Jul 29, 2024
2f112a6
model running status indicator
j-bryan Aug 2, 2024
f5a81ec
run workbench installer silently
j-bryan Aug 11, 2024
c60a7e3
no need to look for Workbench install location
j-bryan Aug 12, 2024
ea7f999
fixes for mac build
j-bryan Aug 20, 2024
4e540fd
simplified FORCE build scripts
j-bryan Sep 30, 2024
c65a73a
Merge branch 'idaholab:main' into package_build
j-bryan Sep 30, 2024
79d191f
removes old commented code
j-bryan Sep 30, 2024
9d8dc6c
converts from 4-space indents to 2-space indents
j-bryan Oct 11, 2024
14b9f20
run in workbench on linux like on windows
j-bryan Oct 11, 2024
6ef0998
updates to readme instructions
j-bryan Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ write_inner.py
.ravenStatus
romMeta.xml

# Ignore built executables
build
force_install
*.app

# Ignore certain GUI files
.forceuirc

# Allow these files
!FORCE_logo-bw.png
!FORCE_logo-color.png


# python stuff
__pycache__
*.pyc
*.pyc
72 changes: 72 additions & 0 deletions package/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# FORCE One-Step Installer Creation
FORCE one-step installers are created using the `cx_Freeze` python package after creating a python environment using either `venv` or `conda`.
A computer with the same operating system and architecture as the target operating system must be used to generate an installer, i.e. use a Windows machine to generate a Windows installer, a Mac (Intel) to generate a Mac installer, etc.
Note that installers generated with Apple computers with M-series chips will not be backwards compatible with Intel-based Apple computers.

Windows and macOS are the only operating systems currently supported.
Linux users are encouraged to use pip-installed or source built versions of the RAVEN, HERON, and TEAL software packages.

## 1. Build FORCE executables
Create a conda environment `force_build_310`, install the RAVEN, HERON, and TEAL pip packages, and build the FORCE executables using the script `build_force.sh`.
dylanjm marked this conversation as resolved.
Show resolved Hide resolved
The path to the conda executable must be provided using the `--conda-defs` argument.
```console
./build_force.sh --conda-defs <path to conda directory>/etc/profile.d/conda.sh
```

## 2. Add IPOPT to build directory (Windows only)
Download the IPOPT Windows binary:
https://github.com/coin-or/Ipopt/releases

Extract the downloaded zip directory and copy its contents to the raven_install directory, ensuring to replace the version numbers of IPOPT as needed.
```console
cd force_install
unzip ~/Downloads/Ipopt-3.14.12-win64-msvs2019-md.zip
mv Ipopt-3.14.12-win64-msvs2019-md local
cd ..
```

## 3. Copy examples and build/copy the RAVEN, HERON, and TEAL documentation
Adding examples and documentation to the one-step installer requires having the source installation present on the build machine, with the `raven_libraries` conda environment already created.
```console
conda activate raven_libraries
joshua-cogliati-inl marked this conversation as resolved.
Show resolved Hide resolved
./copy_examples.sh --raven-dir /path/to/raven --heron-dir /path/to/HERON
cp -R examples force_install/examples
./make_docs.sh --raven-dir /path/to/raven --heron-dir /path/to/HERON --teal-dir /path/to/TEAL
cp -R docs force_install/docs
```
When running the `make_docs.sh` script, the optional `--no-build` flag may be added if the desired documentation PDFs have already been built, and you do not wish to rebuild the documents.
If using the `--no-build` option, there is no need to have the `raven_libraries` active.
```console
./make_docs.sh --no-build --raven-dir /path/to/raven --heron-dir /path/to/HERON --teal-dir /path/to/TEAL
cp -R docs force_install/docs
```

## 4. Get NEAMS Workbench installer
The installers for the NEAMS Workbench software can be found here:
https://code.ornl.gov/neams-workbench/downloads/-/tree/5.4.1?ref_type=heads

Download `Workbench-5.4.1.exe` for Windows and `Workbench-5.4.1.dmg` for macOS.
Place this file in the `force_install` directory on Windows or the current directory on macOS.

Windows:
```console
cp ~/Downloads/Workbench-5.4.1.exe force_install
```

macOS:
```console
cp ~/Downloads/Workbench-5.4.1.dmg .
```

## 5. Create the installer
### Windows
The Windows installer is created using Inno Setup.
Run the `inno_package.iss` script from the Inno Setup application.
The resulting .exe installer file can be found in the `inno_output` directory.

### macOS
Run the macOS build script
```console
./build_mac_app.sh
```
The disk image `FORCE.dmg` contains applications for both FORCE and Workbench.
42 changes: 42 additions & 0 deletions package/build_force.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

# Have users point to the location of their conda installation so we can properly activate the
# conda environment that is being made. Use the "--conda-defs" option to specify this path.
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--conda-defs)
CONDA_DEFS="$2"
shift
shift
source $CONDA_DEFS
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done

# Establish conda environment
conda create -n force_build_310 python=3.10 -y
conda activate force_build_310

# Check that the conda environment is active. If not, exit.
if [[ $CONDA_DEFAULT_ENV != "force_build_310" ]]; then
echo "Conda environment not activated. Maybe the path to the conda installation is incorrect?"
echo "Provided conda path: $CONDA_DEFS"
exit 1
fi

pip install cx_Freeze
pip install raven-framework heron-ravenframework teal-ravenframework
# If on macOS, use conda to install ipopt
if [[ "$OSTYPE" == "darwin"* ]]; then
# Note: The PyPI version of ipopt is not maintained and is severl major version
# behind the conda-forge distribution.
conda install -c conda-forge ipopt -y
fi

# Build the FORCE executables
python setup.py install_exe --install-dir force_install
67 changes: 67 additions & 0 deletions package/build_mac_app.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash

# Set up the FORCE application bundle
# We'll set up the app so that some FORCE launcher script is the main executable, and the RAVEN,
# HERON, and TEAL executables are in the Resources directory.
# Build the initial app from the force_launcher.scpt AppleScript
osacompile -o FORCE.app force_launcher.scpt
# Now copy over the force_install directory contents to the application's Resources directory
cp -Rp force_install/* FORCE.app/Contents/Resources/
# Overwrite the app's icon with the FORCE icon
cp icons/FORCE.icns FORCE.app/Contents/Resources/applet.icns

# Create a new disk image
hdiutil create -size 5g -fs HFS+ -volname "FORCE" -o force_build.dmg

# Mount the new disk image
hdiutil attach force_build.dmg -mountpoint /Volumes/FORCE

# Mount the existing .dmg file file Workbench
hdiutil attach Workbench-5.4.1.dmg -mountpoint /Volumes/Workbench

# Add the workshop tests and data directories to FORCE so that Workbench's autocomplete works for workshop examples
mkdir FORCE.app/Contents/Resources/tests
mkdir FORCE.app/Contents/Resources/examples
cp -Rp examples/workshop FORCE.app/Contents/Resources/tests/
cp -Rp examples/data FORCE.app/Contents/Resources/examples/

# Move the FORCE app to the disk image
cp -Rp FORCE.app /Volumes/FORCE/
cp -Rp /Volumes/Workbench/Workbench-5.4.1.app /Volumes/FORCE/

# Move the "examples" and "docs" directories from the FORCE app bundle to the top level of the disk
# image to make them more accessible.
cp -Rp examples /Volumes/FORCE/
cp -Rp docs /Volumes/FORCE/

# Move the "examples" and "docs" directories from the FORCE app bundle to the top level of the disk
# image to make them more accessible.
if [ -d FORCE.app/Contents/Resources/examples ]; then
mv /Volumes/FORCE/FORCE.app/Contents/Resources/examples /Volumes/FORCE/
else
echo "WARNING: No examples directory found in FORCE.app bundle"
fi
if [ -d FORCE.app/Contents/Resources/docs ]; then
mv FORCE.app/Contents/Resources/docs /Volumes/FORCE/
else
echo "WARNING: No docs directory found in FORCE.app bundle"
fi

# Add .son file to Workbench app to provide a default HERON configuration
cp default.apps.son /Volumes/FORCE/Workbench-5.4.1.app/Contents/

# Create a symlink to the Applications directory in the app's build directory
ln -s /Applications /Volumes/FORCE/Applications

# Unmount all the disk images
hdiutil detach /Volumes/Workbench
hdiutil detach /Volumes/FORCE

# Convert to read-only compressed image
if [ -f FORCE.dmg ]; then
rm FORCE.dmg
fi
hdiutil convert force_build.dmg -format UDZO -o FORCE.dmg

# Remove the temporary disk image
rm force_build.dmg
79 changes: 79 additions & 0 deletions package/copy_examples.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash
# Copies examples from the test directories of RAVEN and HERON to provide examples for users using
# the standalone install version of FORCE.

# Get the RAVEN and HERON locations as arguments "--raven-dir" and "--heron-dir"
# The destination directory is "examples" in the current directory but may be changed with the
# "--dest" argument.
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
EXAMPLES_DIR="$SCRIPT_DIR/examples"

while [[ $# -gt 0 ]]
do
key="$1"
case $key in
--raven-dir)
RAVEN_DIR="$2"
shift
shift
;;
--heron-dir)
HERON_DIR="$2"
shift
shift
;;
--dest)
EXAMPLES_DIR="$2"
shift
shift
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done

# The examples we want to copy are the RAVEN user_guide tests, the HERON workshop tests, and the
# HERON data directory which contains time series models for those workshop tests.
EXAMPLES=($RAVEN_DIR/tests/framework/user_guide $HERON_DIR/data $HERON_DIR/tests/workshop)
mkdir -p $EXAMPLES_DIR

for ex in ${EXAMPLES[@]}; do
cp -R "$ex" "$EXAMPLES_DIR"
done

# Clean up the copied examples, removing files and directories created when running the tests.
DIRS_TO_REMOVE=("__pycache__" "gold" "*_o")
for dirname in ${DIRS_TO_REMOVE[@]}; do
find $EXAMPLES_DIR -type d -name $dirname -exec rm -r {} \; 2>/dev/null
done
FILES_TO_REMOVE=("tests" "moped_input.xml" "outer.xml" "inner.xml" "cash.xml" "*.lib" "write_inner.py" "*.heron" "*.heron.xml")
for filename in ${FILES_TO_REMOVE[@]}; do
find $EXAMPLES_DIR -name $filename -exec rm {} \; 2>/dev/null
done

# If building on Mac, replace the %HERON_DATA% magic string with a relative path to the data
# directory. This is a little hacky but the %HERON_DATA% magic string doesn't look everywhere for
# the data directory. This is only an issue for the Mac standalone install. HERON will find the
# data directory correctly on Windows.
# DATA_DIR=$EXAMPLES_DIR/data
# if [[ "$OSTYPE" == "darwin"* ]]; then
# # Find all XML files recursively from the current directory
# find $EXAMPLES_DIR/workshop -type f -name "*.xml" | while read -r file; do
# # Check if the file contains the %HERON_DATA% magic string. If not, skip this file.
# grep -q "%HERON_DATA%" "$file" || continue

# # Get the directory of the current XML file
# FILE_DIR=$(dirname "$file")

# # Calculate the relative path from the XML file directory to the data directory
# echo "FILE_DIR: $FILE_DIR DATA_DIR: $DATA_DIR"
# RELATIVE_PATH=$(python -c "import os.path; print(os.path.relpath('$DATA_DIR', '$FILE_DIR'))")
# # RELATIVE_PATH=$(realpath -s --relative-to="$FILE_DIR" "$DATA_DIR")
# echo $RELATIVE_PATH

# # Use sed to replace %HERON_DATA% with the relative path to the data directory
# sed -i '' "s|%HERON_DATA%|$RELATIVE_PATH|g" "$file"
# done
# fi
13 changes: 13 additions & 0 deletions package/default.apps.son
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
applications {
HERON {
configurations {
default {
options {
shared {
Executable="/Applications/FORCE.app/Contents/Resources/heron"
}
}
}
}
}
}
28 changes: 28 additions & 0 deletions package/force_launcher.scpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
set options to {"HERON", "RAVEN", "TEAL", "Quit"}

set selectedOption to choose from list options with title "FORCE Launcher" with prompt "Which FORCE application would you like to use?" default items {"HERON"}

if selectedOption is false then
display dialog "No option selected. Exiting..." buttons {"OK"} default button "OK"
else
set selectedOption to item 1 of selectedOption
if selectedOption is "HERON" then
set filePathName to quoted form of "/Applications/FORCE.app/Contents/Resources/heron"
else if selectedOption is "RAVEN" then
set filePathName to quoted form of "/Applications/FORCE.app/Contents/Resources/raven_framework"
else if selectedOption is "TEAL" then
set filePathName to quoted form of "/Applications/FORCE.app/Contents/Resources/teal"
else if selectedOption is "Quit" then
display dialog "Exiting..." buttons {"OK"} default button "OK"
return
end if
-- do shell script filePathName
try
do shell script "test -e " & filePathName
-- If the test passes, the file exists and we proceed with the script
do shell script filePathName
on error
-- If the file doesn't exist, display an error message
display dialog "The file at " & filePathName & " does not exist." buttons {"OK"} default button "OK"
end try
end if
46 changes: 46 additions & 0 deletions package/heron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python
# Copyright 2017 Battelle Energy Alliance, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
import sys
from HERON.src.main import main
from ui import run_from_gui
from utils import add_local_bin_to_path


if __name__ == '__main__':
# Adds the "local/bin" directory to the system path in order to find ipopt and other executables
add_local_bin_to_path()

# Parse the command line arguments
import argparse
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
parser = argparse.ArgumentParser(description='HERON')
parser.add_argument('-w', action='store_true', default=False, required=False, help='Run in the GUI')
parser.add_argument('--definition', action="store_true", dest="definition", help='HERON input file definition compatible with the NEAMS Workbench')
parser.add_argument('input', nargs='?', help='HERON input file')
args, unknown = parser.parse_known_args()

# if the input file is not an xml file, assume it's an unknown argument
if args.input and not args.input.endswith('.xml'):
unknown.insert(0, args.input)
args.input = None
# remove the -w argument from sys.argv so it doesn't interfere with HERON's argument parsing
if args.w:
sys.argv.remove('-w')

if (args.w or not args.input) and not args.definition: # if asked to or if no file is passed, run the GUI
run_from_gui(main)
else:
main()
Loading
Loading