Skip to content

Commit

Permalink
Merge branch '0.3.x_rc'
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane-J-Latham committed May 30, 2017
2 parents 9d3383e + ec5ed07 commit 7c57bb5
Show file tree
Hide file tree
Showing 16 changed files with 341 additions and 77 deletions.
22 changes: 5 additions & 17 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ git:
python:
- '2.6'
- '2.7'
- '3.2'
- '3.3'
- '3.4'
- '3.5'
- '3.6'

install:
- git config --global user.name array-split
- git config --global user.email array-split@users.noreply.github.com
- pwd
- ls -al `pwd`/*
- if [[ $TRAVIS_PYTHON_VERSION != '2.6'* ]]; then pip install flake8; else pip install 'flake8<3'; fi
- pip install 'sphinx>=1.4'
- pip install 'sphinx>=1.4,<1.6'
- pip install travis-sphinx
- pip install coveralls
- python ./setup.py install
Expand All @@ -31,20 +30,9 @@ script:
- cd docs
- python -m array_split.tests
- cd ..
- if [[ $TRAVIS_PYTHON_VERSION != '3.2'* ]]; then travis-sphinx build; fi
- if [[ $TRAVIS_PYTHON_VERSION != '2.6'* ]]; then travis-sphinx build; fi

after_success:
- if [[ $TRAVIS_PYTHON_VERSION != '3.2'* ]]; then travis-sphinx --branches=dev deploy; fi
- if [[ $TRAVIS_PYTHON_VERSION != '3.2'* ]]; then coveralls; fi
- if [[ $TRAVIS_PYTHON_VERSION != '2.6'* ]]; then travis-sphinx --branches=dev deploy; fi
- if [[ $TRAVIS_PYTHON_VERSION != '2.6'* ]]; then coveralls; fi

deploy:
provider: pypi
user: array-split
password:
secure: eGWaz8EWAeU4NohzwB3e6Za8qW+uM0CDWoIuHr98Fii74hsH1+8US2SoG2y/IXvLHsUTxNK6N+nx3aQ0/AQiqpIhBJiYiHpRUPlHh8Zdp4Oh9bRidllGvBlUHSN6LXQHUMcogwHXWybdpgH0ge++rwqs+pGYPjjMSNX1xy5kVmVAIZ6FfORpiY8GOxhVCAAZJyBBLk/zMNZXFZTeNFIn0ebJ9O4ofYOAUpkBbUheA1b9ej7biIwFrkBZu2rJGjgb52cuG/JkS2UbsCQXVvTnbWOxfBh5+kEKdAC8ruAXoSAZEunqLIuCiJ6OQoVF27cGUl1jfuCbkU/qhTyYgQC/7B1CyVTFj3cLkPmIzLbl6C6nhldZe2bbHp8gKjH3sNKPr/0FlUrZGXxQhxvdtrbM9/gi9iCKCsJiZUp+9BOP2kH/JxEkXO4+nbUpCSPqMnB/E8IORIaUhvzKBeTbMrfht/wtdd5BL1wobQcXB4fyvwEXSTTx0TcdIaB6citVQgidu3RvBjKm6ujRqwT7BmjZTvQZzwq6Ap9HNGfeLep/LbwwCJtO1oIuzh5uzFNr3jCDUJa2vC72xwbgTgnwx10Ondwqq6c2HhosVt4aBtqy83j6F+fxrimGIBW17RtQNLqycWvTYi/UJEEc4d3il5+znD3d65D9n8OGRPALbE0Of/M=
skip_cleanup: true
on:
tags: true
branch: master
distributions: "sdist bdist_wheel"
repo: array-split/array_split
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (C) 2016 The Australian National University.
Copyright (C) 2017 The Australian National University.

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
Expand Down
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ Latest sphinx generated documentation is at:

http://array-split.readthedocs.io/en/latest

and at github *gh-pages*:

https://array-split.github.io/array_split/

Sphinx documentation can be built from the source::

python setup.py build_sphinx

with the HTML generated in `docs/build/html`.


Latest source code
==================

Expand Down
2 changes: 1 addition & 1 deletion array_split/copyright.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Copyright (C) 2016 The Australian National University.
Copyright (C) 2017 The Australian National University.
1 change: 1 addition & 0 deletions array_split/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ def emit(self, record):
except:
self.handleError(record)


if (sys.version_info[0] <= 2):
class SplitStreamHandler(_Python2SplitStreamHandler):
__doc__ = _Python2SplitStreamHandler.__doc__
Expand Down
149 changes: 121 additions & 28 deletions array_split/split.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
shape_factors - Compute *largest* factors of a given integer.
calculate_num_slices_per_axis - Computes per-axis divisions for a multi-dimensional shape.
calculate_tile_shape_for_max_bytes - Calculate a tile shape subject to max bytes restriction.
convert_halo_to_array_form - converts halo argument to :samp:`(ndim, 2)` shaped array.
ShapeSplitter - Splits a given shape into slices.
shape_split - Splits a specified shape and returns :obj:`numpy.ndarray` of :obj:`slice` elements.
array_split - Equivalent to :func:`numpy.array_split`.
Expand Down Expand Up @@ -215,21 +216,7 @@ def calculate_tile_shape_for_max_bytes(

sub_tile_shape = _np.array(sub_tile_shape, dtype="int64")

if halo is None:
halo = _np.zeros((len(array_shape), 2), dtype="int64")
elif is_scalar(halo):
halo = _np.zeros((len(array_shape), 2), dtype="int64") + halo
else:
halo = _np.array(halo, copy=True)
if len(halo.shape) == 1:
halo = _np.array([halo, halo]).T.copy()

if halo.shape[0] != len(array_shape):
raise ValueError(
"Got halo.shape=%s, expecting halo.shape=(%s, 2)"
%
(halo.shape, array_shape.shape[0])
)
halo = convert_halo_to_array_form(halo=halo, ndim=len(array_shape))

if _np.any(array_shape < sub_tile_shape):
raise ValueError(
Expand Down Expand Up @@ -411,6 +398,7 @@ def calculate_num_slices_per_axis(num_slices_per_axis, num_slices, max_slices_pe
logger.debug("ridx=%s, f=%s, ret_array=%s", ridx, f, ret_array)
return ret_array


_array_shape_param_doc =\
"""
:type array_shape: sequence of :obj:`int`
Expand Down Expand Up @@ -504,6 +492,7 @@ def ARRAY_BOUNDS():
"""
return __ARRAY_BOUNDS


#: Indicates that tiles may extend beyond the array bounds.
#: See :ref:`the-halo-parameter-examples` examples.
__NO_BOUNDS = "no_bounds"
Expand All @@ -518,6 +507,42 @@ def NO_BOUNDS():
return __NO_BOUNDS


def convert_halo_to_array_form(halo, ndim):
"""
Converts the :samp:`{halo}` argument to a :samp:`(ndim, 2)`
shaped array.
:type halo: :samp:`None`, :obj:`int`, an :samp:`{ndim}` length sequence
of :samp:`int` or :samp:`({ndim}, 2)` shaped array
of :samp:`int`
:param halo: Halo to be converted to :samp:`({ndim}, 2)` shaped array form.
:type ndim: :obj:`int`
:param ndim: Number of dimensions.
:rtype: :obj:`numpy.ndarray`
:return: A :samp:`({ndim}, 2)` shaped array of :obj:`numpy.int64` elements.
"""
dtyp = _np.int64
if halo is None:
halo = _np.zeros((ndim, 2), dtype=dtyp)
elif is_scalar(halo):
halo = _np.zeros((ndim, 2), dtype=dtyp) + halo
elif (ndim == 1) and (_np.array(halo).shape == (2,)):
halo = _np.array([halo, ], copy=True, dtype=dtyp)
elif len(_np.array(halo).shape) == 1:
halo = _np.array([halo, halo], dtype=dtyp).T.copy()
else:
halo = _np.array(halo, copy=True, dtype=dtyp)

if halo.shape[0] != ndim:
raise ValueError(
"Got halo.shape=%s, expecting halo.shape=(%s, 2)"
%
(halo.shape, ndim)
)

return halo


class ShapeSplitter(object):
"""
Implements array shape splitting. There are three main (top-level) methods:
Expand Down Expand Up @@ -607,17 +632,7 @@ def __init__(

self.sub_tile_shape = sub_tile_shape

if halo is None:
halo = _np.zeros((len(self.array_shape), 2), dtype="int64")
elif is_scalar(halo):
halo = _np.zeros((len(self.array_shape), 2), dtype="int64") + halo
elif (len(array_shape) == 1) and (_np.array(halo).shape == (2,)):
halo = _np.array([halo, ], copy=True)
elif len(_np.array(halo).shape) == 1:
halo = _np.array([halo, halo]).T.copy()
else:
halo = _np.array(halo, copy=True)

halo = self.convert_halo_to_array_form(halo)
self.halo = halo

if tile_bounds_policy is None:
Expand All @@ -635,6 +650,20 @@ def __init__(

self.split_ends = None

def convert_halo_to_array_form(self, halo):
"""
Converts the :samp:`{halo}` argument to a :samp:`({self}.array_shape.size, 2)`
shaped array.
:type halo: :samp:`None`, :obj:`int`, :samp:`self.array_shape.size` length sequence
of :samp:`int` or :samp:`(self.array_shape.size, 2)` shaped array
of :samp:`int`
:param halo: Halo to be converted to :samp:`(len(self.array_shape), 2)` shaped array form.
:rtype: :obj:`numpy.ndarray`
:return: A :samp:`(len(self.array_shape), 2)` shaped array of :obj:`numpy.int64` elements.
"""
return convert_halo_to_array_form(halo=halo, ndim=len(self.array_shape))

@property
def array_shape(self):
"""
Expand Down Expand Up @@ -1056,6 +1085,9 @@ def calculate_split_from_extents(self):
"""
Returns split calculated using extents obtained
from :attr:`split_begs` and :attr:`split_ends`.
All calls to calculate the split end up here to produce
the :mod:`numpy` `structured array <http://docs.scipy.org/doc/numpy/user/basics.rec.html>`_
of :obj:`tuple`-of-:obj:`slice` elements.
:rtype: :obj:`numpy.ndarray`
:return:
Expand All @@ -1074,12 +1106,16 @@ def calculate_split_from_extents(self):
slice(
max([
self.split_begs[d][idx[d]]
+ self.array_start[d] - self.halo[d, 0],
+ self.array_start[d]
- self.halo[d, 0]
* (self.split_ends[d][idx[d]] > self.split_begs[d][idx[d]]),
self.tile_beg_min[d]
]),
min([
self.split_ends[d][idx[d]]
+ self.array_start[d] + self.halo[d, 1],
+ self.array_start[d]
+ self.halo[d, 1]
* (self.split_ends[d][idx[d]] > self.split_begs[d][idx[d]]),
self.tile_end_max[d]
])
)
Expand All @@ -1099,6 +1135,58 @@ def calculate_split_from_extents(self):

return ret

def calculate_split_halos_from_extents(self):
"""
Returns :samp:`(self.ndim, 2)` shaped halo array elements indicating
the halo for each split. Tiles on the boundary may have the halo trimmed
to account for the :attr:`tile_bounds_policy`.
:rtype: :obj:`numpy.ndarray`
:return:
A :mod:`numpy` `structured array <http://docs.scipy.org/doc/numpy/user/basics.rec.html>`_
where each element is a :samp:`(self.ndim, 2)` shaped :obj:`numpy.ndarray`
indicating the per-axis and per-direction number of halo elements for each tile
in the split.
"""
self.logger.debug("self.split_shape=%s", self.split_shape)
self.logger.debug("self.split_begs=%s", self.split_begs)
self.logger.debug("self.split_ends=%s", self.split_ends)

ret = \
_np.array(
[
(
tuple(
(
min([
self.split_begs[d][idx[d]] - self.tile_beg_min[d],
self.halo[d, 0]
*
(self.split_ends[d][idx[d]] > self.split_begs[d][idx[d]])
]),
min([
self.tile_end_max[d] - self.split_ends[d][idx[d]],
self.halo[d, 1]
*
(self.split_ends[d][idx[d]] > self.split_begs[d][idx[d]])
])
)
for d in range(len(self.split_shape))
)
)
for idx in
_np.array(
_np.unravel_index(
_np.arange(0, _np.product(self.split_shape)),
self.split_shape
)
).T
],
dtype=[("%d" % d, "2int64") for d in range(len(self.split_shape))]
).reshape(self.split_shape)

return ret

def calculate_split_by_indices_per_axis(self):
"""
Returns split calculated using extents obtained
Expand Down Expand Up @@ -1306,6 +1394,7 @@ def calculate_split(self):
self.set_split_extents()
return self.calculate_split_from_extents()


ShapeSplitter([0, ]).__init__.__func__.__doc__ = \
"""
Initialises parameters which define a split.
Expand Down Expand Up @@ -1338,6 +1427,8 @@ def shape_split(array_shape, *args, **kwargs):
*args,
**kwargs
).calculate_split()


shape_split.__doc__ =\
"""
Splits specified :samp:`{array_shape}` in tiles, returns array of :obj:`slice` tuples.
Expand Down Expand Up @@ -1395,6 +1486,8 @@ def array_split(
tile_bounds_policy=ARRAY_BOUNDS
).flatten()
]


array_split.__doc__ =\
"""
Splits the specified array :samp:`{ary}` into sub-arrays, returns list of :obj:`numpy.ndarray`.
Expand Down
Loading

0 comments on commit 7c57bb5

Please sign in to comment.