forked from tsdev/spinw
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial test of pySpinW * Initial test of pySpinW * Delete SpinW_2023a.ctf * Update versions * Modify build * Update build_pyspinw.yml * Update build_ctf.m * Update build_pyspinw.yml * Update build_pyspinw.yml Remove R2020a, R2020b as too old * Update build_pyspinw.yml Try to fix upload * Update build_pyspinw.yml Try full build script * Adapt package init * Update build_pyspinw.yml Add ctf directory as it was removed * Update build_pyspinw.yml Fix depreciation warning * Update test_spinw.py * Fix license, init and an example * Update test_spinw.py * Update build_pyspinw.yml * Create release_notes.md * Update build_pyspinw.yml Add Tag from version * Try to build mex * Update build_pyspinw.yml * Update build_pyspinw.yml * Update build_pyspinw.yml * Modify remove and find * Update build_pyspinw.yml * Update pyproject.toml * Update build_pyspinw.yml * Some pre-release optimisations * Update build_pyspinw.yml * Reverting back to manual removal of old mex files The find command does not seem to be working on windows, even with a bash shell * Update pyproject.toml * Add version synchronisation * Fix flaky test by specifying seed * Update build_pyspinw.yml
- Loading branch information
Showing
9 changed files
with
535 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
name: pySpinW | ||
|
||
on: [push, workflow_dispatch] | ||
|
||
jobs: | ||
compile_mex: | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, windows-latest, macos-latest] | ||
matlab_version: [latest] | ||
include: | ||
- os: macos-latest | ||
INSTALL_DEPS: brew install llvm libomp | ||
fail-fast: true | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- name: Check out SpinW | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
- name: Set up MATLAB | ||
uses: matlab-actions/setup-matlab@v1 # v1.1.0 required for Windows/MacOS support | ||
with: | ||
release: ${{ matrix.matlab_version }} | ||
|
||
- name: Remove old mex # This is due to find not working :-/ # find ${{ github.workspace }} -name "*.mex*" -type f -delete | ||
run: | | ||
rm external/chol_omp/chol_omp.mexa64 | ||
rm external/chol_omp/chol_omp.mexmaci64 | ||
rm external/chol_omp/chol_omp.mexw64 | ||
rm external/eig_omp/eig_omp.mexa64 | ||
rm external/eig_omp/eig_omp.mexmaci64 | ||
rm external/eig_omp/eig_omp.mexw64 | ||
rm external/mtimesx/sw_mtimesx.mexa64 | ||
rm external/mtimesx/sw_mtimesx.mexmaci64 | ||
rm external/mtimesx/sw_mtimesx.mexw64 | ||
- name: Run MEXing | ||
uses: matlab-actions/run-command@v1 | ||
with: | ||
command: "addpath(genpath('swfiles')); addpath(genpath('external')); sw_mex('compile', true, 'test', false, 'swtest', false);" | ||
- name: Upload MEX results | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: MEX | ||
path: ${{ github.workspace }}/external/**/*.mex* | ||
|
||
build_ctfs: | ||
needs: compile_mex | ||
strategy: | ||
matrix: | ||
matlab_version: [R2021a, R2021b, R2022a, R2022b, R2023a] | ||
runs-on: self-hosted | ||
steps: | ||
- name: Check out SpinW | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
- name: Download MEX artifacts | ||
uses: actions/download-artifact@v3 | ||
with: | ||
name: MEX | ||
path: ${{ github.workspace }}/external | ||
- name: Build ctf | ||
run: | | ||
cd python | ||
/Applications/MATLAB_${{ matrix.matlab_version }}.app/bin/matlab -nodisplay -r "build_ctf; exit" | ||
- name: Upload CTF results | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: CTF | ||
path: ${{ github.workspace }}/python/ctf/*.ctf | ||
|
||
build_wheel: | ||
runs-on: ubuntu-latest | ||
needs: build_ctfs | ||
permissions: | ||
contents: write | ||
steps: | ||
- name: Checkout SpinW | ||
uses: actions/checkout@v3 | ||
- name: Download CTF artifacts | ||
uses: actions/download-artifact@v3 | ||
with: | ||
name: CTF | ||
path: python/ctf | ||
- name: Set up Python environment | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: 3.8 | ||
- name: Move files | ||
run: | | ||
cd python | ||
echo "PYSPINW_VERSION=$( cat pyproject.toml | grep "version = \"" | awk -F'"' '$0=$2' | sed 's/ //g' )" >> $GITHUB_ENV | ||
mkdir pyspinw/ctfs | ||
mv ctf/*.ctf pyspinw/ctfs | ||
- name: Update Versions | ||
if: startsWith(github.ref, 'refs/tags/v') | ||
run: | | ||
pip install poetry | ||
cd ${{ github.workspace }}/python | ||
poetry version $(git describe --tags --abbrev=0) | ||
- name: Build Wheel | ||
run: | | ||
cd ${{ github.workspace }}/python | ||
python -m pip wheel --no-deps --wheel-dir build . | ||
- name: Create wheel artifact | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: pySpinW Wheel | ||
path: ${{ github.workspace }}/python/build/*.whl | ||
- uses: ncipollo/release-action@v1 | ||
if: startsWith(github.ref, 'refs/tags/v') | ||
with: | ||
artifacts: ${{ github.workspace }}/python/build/*.whl | ||
prerelease: true | ||
replacesArtifacts: true | ||
name: "pySpinW" | ||
bodyFile: ${{ github.workspace }}/python/release_notes.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
out_dir = 'ctf'; | ||
VERSION = version('-release'); | ||
package_name = ['SpinW_', VERSION]; | ||
full_package = ['SpinW_', VERSION, '.ctf']; | ||
|
||
opts = compiler.build.ProductionServerArchiveOptions( ... | ||
['matlab', filesep, 'call.m'], ... | ||
'ArchiveName', package_name, ... | ||
'OutputDir', out_dir, ... | ||
'AutoDetectDataFiles', 'on', ... | ||
'AdditionalFiles', { ... | ||
['..', filesep, 'swfiles'], ... | ||
['..', filesep, 'external'], ... | ||
['..', filesep, 'dat_files']}); | ||
|
||
compiler.build.productionServerArchive(opts); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
function [varargout] = call(name, varargin) | ||
if strcmp(name, '_call_python') | ||
varargout = call_python_m(varargin{:}); | ||
return | ||
end | ||
resultsize = nargout; | ||
try | ||
maxresultsize = nargout(name); | ||
if maxresultsize == -1 | ||
maxresultsize = resultsize; | ||
end | ||
catch | ||
maxresultsize = resultsize; | ||
end | ||
if resultsize > maxresultsize | ||
resultsize = maxresultsize; | ||
end | ||
if nargin == 1 | ||
args = {}; | ||
else | ||
args = varargin; | ||
end | ||
for ir = 1:numel(args) | ||
args{ir} = unwrap(args{ir}); | ||
end | ||
if resultsize > 0 | ||
% call the function with the given number of | ||
% output arguments: | ||
varargout = cell(resultsize, 1); | ||
try | ||
[varargout{:}] = feval(name, args{:}); | ||
catch err | ||
if (strcmp(err.identifier,'MATLAB:unassignedOutputs')) | ||
varargout = eval_ans(name, args); | ||
else | ||
rethrow(err); | ||
end | ||
end | ||
else | ||
varargout = eval_ans(name, args); | ||
end | ||
for ir = 1:numel(varargout) | ||
varargout{ir} = wrap(varargout{ir}); | ||
end | ||
end | ||
|
||
function out = unwrap(in_obj) | ||
out = in_obj; | ||
if isstruct(in_obj) && isfield(in_obj, 'func_ptr') && isfield(in_obj, 'converter') | ||
out = @(varargin) call('_call_python', [in_obj.func_ptr, in_obj.converter], varargin{:}); | ||
elseif isa(in_obj, 'containers.Map') && in_obj.isKey('wrapped_oldstyle_class') | ||
out = in_obj('wrapped_oldstyle_class'); | ||
elseif iscell(in_obj) | ||
for ii = 1:numel(in_obj) | ||
out{ii} = unwrap(in_obj{ii}); | ||
end | ||
end | ||
end | ||
|
||
function out = wrap(obj) | ||
out = obj; | ||
if isobject(obj) && (isempty(metaclass(obj)) && ~isjava(obj)) || has_thin_members(obj) | ||
out = containers.Map({'wrapped_oldstyle_class'}, {obj}); | ||
elseif iscell(obj) | ||
for ii = 1:numel(obj) | ||
out{ii} = wrap(obj{ii}); | ||
end | ||
end | ||
end | ||
|
||
function out = has_thin_members(obj) | ||
% Checks whether any member of a class or struct is an old-style class | ||
% or is already a wrapped instance of such a class | ||
out = false; | ||
if isobject(obj) || isstruct(obj) | ||
try | ||
fn = fieldnames(obj); | ||
catch | ||
return; | ||
end | ||
for ifn = 1:numel(fn) | ||
try | ||
mem = subsref(obj, struct('type', '.', 'subs', fn{ifn})); | ||
catch | ||
continue; | ||
end | ||
if (isempty(metaclass(mem)) && ~isjava(mem)) | ||
out = true; | ||
break; | ||
end | ||
end | ||
end | ||
end | ||
|
||
function results = eval_ans(name, args) | ||
% try to get output from ans: | ||
clear('ans'); | ||
feval(name, args{:}); | ||
try | ||
results = {ans}; | ||
catch err | ||
results = {[]}; | ||
end | ||
end | ||
|
||
function [n, undetermined] = getArgOut(name, parent) | ||
undertermined = false; | ||
if isstring(name) | ||
fun = str2func(name); | ||
try | ||
n = nargout(fun); | ||
catch % nargout fails if fun is a method: | ||
try | ||
n = nargout(name); | ||
catch | ||
n = 1; | ||
undetermined = true; | ||
end | ||
end | ||
else | ||
n = 1; | ||
undetermined = true; | ||
end | ||
end | ||
|
||
function out = call_python_m(varargin) | ||
% Convert row vectors to column vectors for better conversion to numpy | ||
for ii = 1:numel(varargin) | ||
if size(varargin{ii}, 1) == 1 | ||
varargin{ii} = varargin{ii}'; | ||
end | ||
end | ||
fun_name = varargin{1}; | ||
[kw_args, remaining_args] = get_kw_args(varargin(2:end)); | ||
if ~isempty(kw_args) | ||
remaining_args = [remaining_args {struct('pyHorace_pyKwArgs', 1, kw_args{:})}]; | ||
end | ||
out = call_python(fun_name, remaining_args{:}); | ||
if ~iscell(out) | ||
out = {out}; | ||
end | ||
end | ||
|
||
function [kw_args, remaining_args] = get_kw_args(args) | ||
% Finds the keyword arguments (string, val) pairs, assuming that they always at the end (last 2n items) | ||
first_kwarg_id = numel(args) + 1; | ||
for ii = (numel(args)-1):-2:1 | ||
if ischar(args{ii}); args{ii} = string(args{ii}(:)'); end | ||
if isstring(args{ii}) && ... | ||
strcmp(regexp(args{ii}, '^[A-Za-z_][A-Za-z0-9_]*', 'match'), args{ii}) | ||
% Python identifiers must start with a letter or _ and can contain charaters, numbers or _ | ||
first_kwarg_id = ii; | ||
else | ||
break; | ||
end | ||
end | ||
if first_kwarg_id < numel(args) | ||
kw_args = args(first_kwarg_id:end); | ||
remaining_args = args(1:(first_kwarg_id-1)); | ||
else | ||
kw_args = {}; | ||
remaining_args = args; | ||
end | ||
end |
Oops, something went wrong.