Skip to content

Commit

Permalink
Merge pull request #14 from ufo-kit/ci
Browse files Browse the repository at this point in the history
Add github actions test
  • Loading branch information
tfarago committed May 18, 2022
2 parents 81f8c31 + 9709998 commit e84932e
Show file tree
Hide file tree
Showing 19 changed files with 214 additions and 161 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: syris tests

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10']
fail-fast: false
steps:
- uses: actions/checkout@v3
- name: Display Ubuntu version
run: lsb_release -d
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Display python version
run: python --version
- name: Install dependencies
run: |
sudo apt-get install -qq python3-pyopencl
python -m pip install --upgrade pip
pip install flake8 pytest coverage
pip install -r requirements.txt
- name: Run tests with coverage
run: |
coverage run -m --source=syris unittest discover -v
- name: Upload coverage to Codecov
if: matrix.python-version == 3.8
uses: codecov/codecov-action@v2
with:
fail_ci_if_error: true
verbose: true
5 changes: 3 additions & 2 deletions syris/bodies/isosurfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array
import pyopencl.cltypes as cltypes
import quantities as q
import syris.gpu.util as g_util
import syris.geometry as geom
Expand Down Expand Up @@ -185,8 +186,8 @@ def project_metaballs(metaballs, shape, pixel_size, offset=None, queue=None, out
right_mem,
np.int32(len(metaballs)),
offset,
cl_array.vec.make_int2(0, 0),
cl_array.vec.make_int4(0, 0, m, n),
cltypes.make_int2(0, 0),
cltypes.make_int4(0, 0, m, n),
g_util.make_vfloat2(ps[1], ps[0]),
np.int32(True),
)
Expand Down
7 changes: 4 additions & 3 deletions syris/bodies/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re
import numpy as np
import pyopencl.array as cl_array
import pyopencl.cltypes as cltypes
import quantities as q
import syris.config as cfg
import syris.geometry as geom
Expand Down Expand Up @@ -182,7 +183,7 @@ def sort(self):
representatives = np.argmax(x, axis=1) + factor
# Get indices which sort the triangles
base = 3 * np.argsort(self._current[0, representatives])
indices = np.empty(3 * len(base), dtype=np.int)
indices = np.empty(3 * len(base), dtype=int)
indices[::3] = base
indices[1::3] = base + 1
indices[2::3] = base + 2
Expand All @@ -207,7 +208,7 @@ def get_degenerate_triangles(self, eps=1e-3 * q.deg):
indices = np.where(diff < eps)[0]

# Stretch to vertex indices
t_indices = np.empty(3 * len(indices), dtype=np.int)
t_indices = np.empty(3 * len(indices), dtype=int)
for i in range(3):
t_indices[i::3] = 3 * indices + i
close = self._current[:-1, t_indices]
Expand Down Expand Up @@ -279,7 +280,7 @@ def get_px_value(value, round_func, ps):
y_max_px = get_px_value(y_max, np.ceil, pixel_size[0])
width = min(x_max_px - x_min_px, shape[1])
height = min(y_max_px - y_min_px, shape[0])
compute_offset = cl_array.vec.make_int2(x_min_px, y_min_px)
compute_offset = cltypes.make_int2(x_min_px, y_min_px)
v_1, v_2, v_3 = self._make_inputs(queue, pixel_size)
max_dx = self.max_triangle_x_diff.simplified.magnitude / psm[1]
# Use the same pixel size as for the x-axis, which will work for objects "not too far"
Expand Down
4 changes: 2 additions & 2 deletions syris/bodies/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def _project(self, shape, pixel_size, offset, t=None, queue=None, out=None, bloc
orig_shape = self.thickness.shape
orig_region = (0, 0) + orig_shape
end = ((offset + shape * pixel_size) / self.pixel_size).simplified.magnitude
end = np.round(end).astype(np.int)
start = np.round((offset / self.pixel_size).simplified.magnitude).astype(np.int)
end = np.round(end).astype(int)
start = np.round((offset / self.pixel_size).simplified.magnitude).astype(int)
# numpy integers are not understood by pyopencl's rectangle copy
end = [int(num) for num in end]
start = [int(num) for num in start]
Expand Down
4 changes: 2 additions & 2 deletions syris/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array
import pyopencl.cltypes as cltypes


LOG = logging.getLogger()
Expand Down Expand Up @@ -45,7 +45,7 @@ def set_precision(self, double):

dtype_base = "double" if double else "float"
for i in [2, 3, 4, 8, 16]:
setattr(self, "vfloat" + str(i), getattr(cl_array.vec, dtype_base + str(i)))
setattr(self, "vfloat" + str(i), getattr(cltypes, dtype_base + str(i)))


class OpenCL(object):
Expand Down
6 changes: 3 additions & 3 deletions syris/gpu/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array
import pyopencl.cltypes as cltypes
import quantities as q
from multiprocessing.pool import ThreadPool
from pyopencl.array import vec
from syris import profiling as prf
from syris import config as cfg
import logging
Expand Down Expand Up @@ -456,9 +456,9 @@ def _make_vfloat_functions():
def _wrapper(i):
def make_vfloat(*args):
if cfg.PRECISION.is_single():
return getattr(vec, "make_float%d" % (i))(*args)
return getattr(cltypes, "make_float%d" % (i))(*args)
else:
return getattr(vec, "make_double%d" % (i))(*args)
return getattr(cltypes, "make_double%d" % (i))(*args)

make_vfloat.__name__ = "make_vfloat%d" % (i)
return make_vfloat
Expand Down
8 changes: 4 additions & 4 deletions syris/imageprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array
from pyopencl.array import vec
import pyopencl.cltypes as cltypes
from reikna.cluda import ocl_api
from reikna.fft import FFT
from syris import config as cfg
Expand Down Expand Up @@ -201,9 +201,9 @@ def bin_image(image, summed_shape, offset=(0, 0), average=False, out=None, queue
None,
out.data,
image.data,
vec.make_int2(*region[::-1]),
cltypes.make_int2(*region[::-1]),
np.int32(image.shape[1]),
vec.make_int2(*offset[::-1]),
cltypes.make_int2(*offset[::-1]),
np.int32(average),
)
if block:
Expand Down Expand Up @@ -362,7 +362,7 @@ def _varconvolve_2d_parametrized(
)
)
image = g_util.get_image(image, queue=queue)
args = (image, out.data, sampler, cl_array.vec.make_int2(0, 0), parameters.data)
args = (image, out.data, sampler, cltypes.make_int2(0, 0), parameters.data)

varconvolve(kernel_name, image.shape[::-1], args, queue=queue, block=block)

Expand Down
12 changes: 7 additions & 5 deletions syris/materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ def save(self, filename=None):
"""Save this instance to a *filename*."""
if filename is None:
filename = "{}.mat".format(self.name)
pickle.dump(self, open(filename, "wb"))
with open(filename, 'wb') as f:
pickle.dump(self, f)

def __eq__(self, other):
return isinstance(other, Material) and self.name == other.name
Expand Down Expand Up @@ -333,7 +334,8 @@ def make_stepanov(name, energies, density=None, formula=None, crystal=None):

def make_fromfile(filename):
"""Load saved material from *filename*."""
return pickle.load(open(filename, "rb"))
with open(filename, "rb") as f:
return pickle.load(f)


class _HenkeQuery(object):
Expand Down Expand Up @@ -434,9 +436,9 @@ def _parse_henke(response):
"""
split = [line.split() for line in response]
energies, delta, beta = list(zip(*split))
delta = np.array(delta).astype(np.float)
beta = np.array(beta).astype(np.float)
energies = np.array(energies).astype(np.float)
delta = np.array(delta).astype(float)
beta = np.array(beta).astype(float)
energies = np.array(energies).astype(float)

return energies, (delta + beta * 1j).astype(cfg.PRECISION.np_cplx)

Expand Down
4 changes: 2 additions & 2 deletions syris/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ def difference_root(x_0, tck, y_d):

def get_root(up=1):
y_s = interp.splev(x_0, tck) + up * y_d
t, c, k = np.copy(tck)
t, c, k = tck
# Adjust spline coefficients to be able to find f(x) = 0.
c -= y_s
c = c - y_s

return closest(interp.sproot((t, c, k)), x_0)

Expand Down
108 changes: 54 additions & 54 deletions syris/tests/test_bodies.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import numpy as np
import quantities as q
import syris.config as cfg
import unittest
from syris import geometry as geom
from syris.geometry import Trajectory
from syris.bodies.base import CompositeBody
from syris.bodies.isosurfaces import MetaBall
from syris.bodies.mesh import make_cube, Mesh
from syris.bodies.simple import StaticBody
from syris.imageprocessing import crop, pad, rescale
from syris.tests import default_syris_init, SyrisTest
from syris.tests import are_images_supported, default_syris_init, SyrisTest
import itertools
from syris.tests.graphics_util import get_linear_points

Expand All @@ -17,59 +18,6 @@ def get_control_points():
return np.array([(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 0, 1), (1, 1, 1)]) * q.mm


def test_simple():
default_syris_init()
n = 8
ps = 1 * q.um
thickness = np.arange(n ** 2).reshape(n, n).astype(cfg.PRECISION.np_float) * q.m
go = StaticBody(thickness, ps)

# Same
projection = go.project((n, n), ps).get()
np.testing.assert_almost_equal(thickness.magnitude, projection)

# Cropped upsampled
shape = (n, n)
gt = rescale(thickness.magnitude, shape).get()
projection = go.project(shape, ps / 2).get()
gt = rescale(crop(thickness.magnitude, (0, 0, n // 2, n // 2)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Cropped downsampled
shape = (n // 4, n // 4)
gt = rescale(thickness.magnitude, shape).get()
projection = go.project(shape, 2 * ps).get()
gt = rescale(crop(thickness.magnitude, (0, 0, n // 2, n // 2)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Padded upsampled
shape = (4 * n, 4 * n)
projection = go.project(shape, ps / 2, offset=(-n // 2, -n // 2) * ps).get()
gt = rescale(pad(thickness.magnitude, (n // 2, n // 2, 2 * n, 2 * n)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Padded downsampled
shape = (n, n)
projection = go.project(shape, 2 * ps, offset=(-n // 2, -n // 2) * ps).get()
gt = rescale(pad(thickness.magnitude, (4, 4, 2 * n, 2 * n)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Crop and pad and upsample
def crop_pad_rescale(ss):
shape = (n, n)
target_ps = ps / ss
offset = (2, -2) * q.um
shape = (int(n // 2 * ss), int(ss * 3 * n // 2))
projection = go.project(shape, target_ps, offset=offset).get()
gt = rescale(
pad(thickness[n // 4 : 3 * n // 4, :], (0, n // 4, n // 2, 3 * n // 2)), shape
).get()
np.testing.assert_almost_equal(gt, projection)

crop_pad_rescale(2)
crop_pad_rescale(0.5)


class TestBodies(SyrisTest):
def setUp(self):
default_syris_init()
Expand All @@ -81,6 +29,58 @@ def setUp(self):
self.metaball_2 = MetaBall(Trajectory(get_linear_points(geom.Z)), 2 * q.mm)
self.composite = CompositeBody(traj, bodies=[self.metaball, self.metaball_2])

@unittest.skipIf(not are_images_supported(), "Images not supported")
def test_simple(self):
n = 8
ps = 1 * q.um
thickness = np.arange(n ** 2).reshape(n, n).astype(cfg.PRECISION.np_float) * q.m
go = StaticBody(thickness, ps)

# Same
projection = go.project((n, n), ps).get()
np.testing.assert_almost_equal(thickness.magnitude, projection)

# Cropped upsampled
shape = (n, n)
gt = rescale(thickness.magnitude, shape).get()
projection = go.project(shape, ps / 2).get()
gt = rescale(crop(thickness.magnitude, (0, 0, n // 2, n // 2)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Cropped downsampled
shape = (n // 4, n // 4)
gt = rescale(thickness.magnitude, shape).get()
projection = go.project(shape, 2 * ps).get()
gt = rescale(crop(thickness.magnitude, (0, 0, n // 2, n // 2)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Padded upsampled
shape = (4 * n, 4 * n)
projection = go.project(shape, ps / 2, offset=(-n // 2, -n // 2) * ps).get()
gt = rescale(pad(thickness.magnitude, (n // 2, n // 2, 2 * n, 2 * n)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Padded downsampled
shape = (n, n)
projection = go.project(shape, 2 * ps, offset=(-n // 2, -n // 2) * ps).get()
gt = rescale(pad(thickness.magnitude, (4, 4, 2 * n, 2 * n)), shape).get()
np.testing.assert_almost_equal(gt, projection)

# Crop and pad and upsample
def crop_pad_rescale(ss):
shape = (n, n)
target_ps = ps / ss
offset = (2, -2) * q.um
shape = (int(n // 2 * ss), int(ss * 3 * n // 2))
projection = go.project(shape, target_ps, offset=offset).get()
gt = rescale(
pad(thickness[n // 4 : 3 * n // 4, :], (0, n // 4, n // 2, 3 * n // 2)), shape
).get()
np.testing.assert_almost_equal(gt, projection)

crop_pad_rescale(2)
crop_pad_rescale(0.5)

def _get_moved_bounding_box(self, body, angle):
body.translate((1, 0, 0) * q.mm)
body.rotate(angle, np.array((0, 0, 1)))
Expand Down
2 changes: 1 addition & 1 deletion syris/tests/test_gpu_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def _test():
self.assertRaises(TypeError, gu.get_image, None)

# Complex Image
data = np.ones((4, 4), dtype=np.complex)
data = np.ones((4, 4), dtype=complex)
self.assertRaises(TypeError, gu.get_image, data)

def test_get_duration(self):
Expand Down

0 comments on commit e84932e

Please sign in to comment.