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

CI: add 32-bit Win to CI #2696

Merged
merged 5 commits into from
May 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
49 changes: 49 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
trigger:
# start a new build for every push
batch: False
branches:
include:
- develop
paths:
include:
- '*'

pr:
branches:
include:
- '*' # must quote since "*" is a YAML reserved character; we want a string


jobs:
- job: Windows
condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master')) # skip for PR merges
pool:
vmImage: 'VS2017-Win2016'
strategy:
maxParallel: 4
matrix:
Python37-32bit-full:
PYTHON_VERSION: '3.7'
PYTHON_ARCH: 'x86'
BITS: 32
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: $(PYTHON_VERSION)
addToPath: true
architecture: $(PYTHON_ARCH)
- script: python -m pip install --upgrade pip setuptools wheel
displayName: 'Install tools'
- script: python -m pip install numpy scipy cython pytest pytest-xdist matplotlib
displayName: 'Install dependencies'
- powershell: |
cd package
python setup.py install
cd ..\testsuite
python setup.py install
cd ..
displayName: 'Build MDAnalysis'
- powershell: |
cd testsuite
pytest .\MDAnalysisTests --disable-pytest-warnings -n 2
displayName: 'Run MDAnalysis Test Suite'
4 changes: 3 additions & 1 deletion package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ mm/dd/yy richardjgowers, kain88-de, lilyminium, p-j-smith, bdice, joaomcteixeira
PicoCentauri, davidercruz, jbarnoud, RMeli, IAlibay, mtiberti, CCook96,
Yuan-Yu, xiki-tempula, HTian1997, Iv-Hristov, hmacdope, AnshulAngaria,
ss62171, Luthaf, yuxuanzhuang, abhishandy, mlnance, shfrz, orbeckst,
wvandertoorn, cbouy, AmeyaHarmalkar, Oscuro-Phoenix, andrrizzi, WG150
wvandertoorn, cbouy, AmeyaHarmalkar, Oscuro-Phoenix, andrrizzi, WG150,
tylerjereddy

* 0.21.0

Expand Down Expand Up @@ -87,6 +88,7 @@ Fixes
* Contact Analysis class respects PBC (Issue #2368)

Enhancements
* vastly improved support for 32-bit Windows (PR #2696)
* Added methods to compute the root-mean-square-inner-product of subspaces
and the cumulative overlap of a vector in a subspace for PCA (PR #2613)
* Added .frames and .times arrays to AnalysisBase (Issue #2661)
Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/core/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class ByResSelection(UnarySelection):

def apply(self, group):
res = self.sel.apply(group)
unique_res = unique_int_1d(res.resindices.astype(np.int64))
unique_res = unique_int_1d(res.resindices)
mask = np.in1d(group.resindices, unique_res)

return group[mask].unique
Expand Down
4 changes: 2 additions & 2 deletions package/MDAnalysis/core/topologyattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1474,7 +1474,7 @@ class Molnums(ResidueAttr):
attrname = 'molnums'
singular = 'molnum'
target_classes = [AtomGroup, ResidueGroup, Atom, Residue]
dtype = np.int64
dtype = np.intp

# segment attributes

Expand Down Expand Up @@ -1730,7 +1730,7 @@ def fragindices(self):
.. versionadded:: 0.20.0
"""
fragdict = self.universe._fragdict
return np.array([fragdict[aix].ix for aix in self.ix], dtype=np.int64)
return np.array([fragdict[aix].ix for aix in self.ix], dtype=np.intp)

def fragment(self):
"""An :class:`~MDAnalysis.core.groups.AtomGroup` representing the
Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/lib/NeighborSearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def search(self, atoms, radius, level='A'):
radius, box=self._box, return_distances=False)

if pairs.size > 0:
unique_idx = unique_int_1d(np.asarray(pairs[:, 1], dtype=np.int64))
unique_idx = unique_int_1d(np.asarray(pairs[:, 1], dtype=np.intp))
return self._index2level(unique_idx, level)

def _index2level(self, indices, level):
Expand Down
6 changes: 3 additions & 3 deletions package/MDAnalysis/lib/_augment.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,12 @@ def augment_coordinates(float[:, ::1] coordinates, float[:] box, float r):
output.push_back(coord[j] - shiftZ[j])
indices.push_back(i)
n = indices.size()
return np.asarray(output, dtype=np.float32).reshape(n, 3), np.asarray(indices, dtype=np.int64)
return np.asarray(output, dtype=np.float32).reshape(n, 3), np.asarray(indices, dtype=np.intp)


@cython.boundscheck(False)
@cython.wraparound(False)
def undo_augment(np.int64_t[:] results, np.int64_t[:] translation, int nreal):
def undo_augment(np.intp_t[:] results, np.intp_t[:] translation, int nreal):
"""Translate augmented indices back to original indices.

Parameters
Expand Down Expand Up @@ -339,4 +339,4 @@ def undo_augment(np.int64_t[:] results, np.int64_t[:] translation, int nreal):
for i in range(N):
if results[i] >= nreal:
results[i] = translation[results[i] - nreal]
return np.asarray(results, dtype=np.int64)
return np.asarray(results, dtype=np.intp)
4 changes: 2 additions & 2 deletions package/MDAnalysis/lib/_cutil.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ ctypedef cmap[int, intset] intmap

@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False) # turn off negative index wrapping for entire function
def unique_int_1d(np.int64_t[:] values):
def unique_int_1d(np.intp_t[:] values):
"""Find the unique elements of a 1D array of integers.

This function is optimal on sorted arrays.
Expand All @@ -71,7 +71,7 @@ def unique_int_1d(np.int64_t[:] values):
cdef int i = 0
cdef int j = 0
cdef int n_values = values.shape[0]
cdef np.int64_t[:] result = np.empty(n_values, dtype=np.int64)
cdef np.intp_t[:] result = np.empty(n_values, dtype=np.intp)

if n_values == 0:
return np.array(result)
Expand Down
12 changes: 6 additions & 6 deletions package/MDAnalysis/lib/distances.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def _bruteforce_capped(reference, configuration, max_cutoff, min_cutoff=None,
``configuration[pairs[k, 1]]``.
"""
# Default return values (will be overwritten only if pairs are found):
pairs = np.empty((0, 2), dtype=np.int64)
pairs = np.empty((0, 2), dtype=np.intp)
distances = np.empty((0,), dtype=np.float64)

if len(reference) > 0 and len(configuration) > 0:
Expand Down Expand Up @@ -605,7 +605,7 @@ def _pkdtree_capped(reference, configuration, max_cutoff, min_cutoff=None,
from .pkdtree import PeriodicKDTree # must be here to avoid circular import

# Default return values (will be overwritten only if pairs are found):
pairs = np.empty((0, 2), dtype=np.int64)
pairs = np.empty((0, 2), dtype=np.intp)
distances = np.empty((0,), dtype=np.float64)

if len(reference) > 0 and len(configuration) > 0:
Expand Down Expand Up @@ -685,7 +685,7 @@ def _nsgrid_capped(reference, configuration, max_cutoff, min_cutoff=None,
``configuration[pairs[k, 1]]``.
"""
# Default return values (will be overwritten only if pairs are found):
pairs = np.empty((0, 2), dtype=np.int64)
pairs = np.empty((0, 2), dtype=np.intp)
distances = np.empty((0,), dtype=np.float64)

if len(reference) > 0 and len(configuration) > 0:
Expand Down Expand Up @@ -919,7 +919,7 @@ def _bruteforce_capped_self(reference, max_cutoff, min_cutoff=None, box=None,
Added `return_distances` keyword.
"""
# Default return values (will be overwritten only if pairs are found):
pairs = np.empty((0, 2), dtype=np.int64)
pairs = np.empty((0, 2), dtype=np.intp)
distances = np.empty((0,), dtype=np.float64)

N = len(reference)
Expand Down Expand Up @@ -996,7 +996,7 @@ def _pkdtree_capped_self(reference, max_cutoff, min_cutoff=None, box=None,
from .pkdtree import PeriodicKDTree # must be here to avoid circular import

# Default return values (will be overwritten only if pairs are found):
pairs = np.empty((0, 2), dtype=np.int64)
pairs = np.empty((0, 2), dtype=np.intp)
distances = np.empty((0,), dtype=np.float64)

# We're searching within a single coordinate set, so we need at least two
Expand Down Expand Up @@ -1068,7 +1068,7 @@ def _nsgrid_capped_self(reference, max_cutoff, min_cutoff=None, box=None,
Added `return_distances` keyword.
"""
# Default return values (will be overwritten only if pairs are found):
pairs = np.empty((0, 2), dtype=np.int64)
pairs = np.empty((0, 2), dtype=np.intp)
distances = np.empty((0,), dtype=np.float64)

# We're searching within a single coordinate set, so we need at least two
Expand Down
2 changes: 1 addition & 1 deletion package/MDAnalysis/lib/nsgrid.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ cdef class NSResults(object):
and initial atom coordinates of shape ``(N, 2)``
"""

return np.asarray(self.pairs_buffer, dtype=np.int64).reshape(self.npairs, 2)
return np.asarray(self.pairs_buffer, dtype=np.intp).reshape(self.npairs, 2)

def get_pair_distances(self):
"""Returns all the distances corresponding to each pair of neighbors
Expand Down
10 changes: 5 additions & 5 deletions package/MDAnalysis/lib/pkdtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def search(self, centers, radius):
radius))
self._indices = np.array(list(
itertools.chain.from_iterable(indices)),
dtype=np.int64)
dtype=np.intp)
if self._indices.size > 0:
self._indices = undo_augment(self._indices,
self.mapping,
Expand All @@ -200,7 +200,7 @@ def search(self, centers, radius):
radius))
self._indices = np.array(list(
itertools.chain.from_iterable(indices)),
dtype=np.int64)
dtype=np.intp)
self._indices = np.asarray(unique_int_1d(self._indices))
return self._indices

Expand Down Expand Up @@ -234,7 +234,7 @@ def search_pairs(self, radius):
if self.cutoff < radius:
raise RuntimeError('Set cutoff greater or equal to the radius.')

pairs = np.array(list(self.ckdt.query_pairs(radius)), dtype=np.int64)
pairs = np.array(list(self.ckdt.query_pairs(radius)), dtype=np.intp)
if self.pbc:
if len(pairs) > 1:
pairs[:, 0] = undo_augment(pairs[:, 0], self.mapping,
Expand Down Expand Up @@ -294,7 +294,7 @@ class initialization
other_tree = cKDTree(wrapped_centers, leafsize=self.leafsize)
pairs = other_tree.query_ball_tree(self.ckdt, radius)
pairs = np.array([[i, j] for i, lst in enumerate(pairs) for j in lst],
dtype=np.int64)
dtype=np.intp)
if pairs.size > 0:
pairs[:, 1] = undo_augment(pairs[:, 1],
self.mapping,
Expand All @@ -303,7 +303,7 @@ class initialization
other_tree = cKDTree(centers, leafsize=self.leafsize)
pairs = other_tree.query_ball_tree(self.ckdt, radius)
pairs = np.array([[i, j] for i, lst in enumerate(pairs) for j in lst],
dtype=np.int64)
dtype=np.intp)
if pairs.size > 0:
pairs = unique_rows(pairs)
return pairs
4 changes: 4 additions & 0 deletions testsuite/MDAnalysisTests/analysis/test_density.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,8 @@ class TestNotWithin(object):
def u():
return mda.Universe(GRO)

@pytest.mark.skipif(sys.maxsize <= 2**32,
reason="non-kdtree density too large for 32-bit")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memory allocation issue specifically, I think

def test_within(self, u):
vers1 = density.notwithin_coordinates_factory(u, 'resname SOL',
'protein', 2,
Expand All @@ -410,6 +412,8 @@ def test_within(self, u):

assert_equal(vers1, vers2)

@pytest.mark.skipif(sys.maxsize <= 2**32,
reason="non-kdtree density too large for 32-bit")
def test_not_within(self, u):
vers1 = density.notwithin_coordinates_factory(u, 'resname SOL',
'protein', 2,
Expand Down
4 changes: 4 additions & 0 deletions testsuite/MDAnalysisTests/analysis/test_hole2.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def test_relative(self):
fixed = check_and_fix_long_filename(abspath)
assert fixed == self.filename

@pytest.mark.skipif(os.name == 'nt' and sys.maxsize <= 2**32,
reason="FileNotFoundError on Win 32-bit")
def test_symlink_dir(self, tmpdir):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this also because of not having symlinking privileges, or is it some weirdness with Windows paths and os.path.join?

(Just out of interest; I'm not sure hole2 even supports Windows.)

dirname = 'really_'*20 +'long_name'
short_name = self.filename[-20:]
Expand All @@ -86,6 +88,8 @@ def test_symlink_dir(self, tmpdir):
assert os.path.islink(fixed)
assert fixed.endswith(short_name)

@pytest.mark.skipif(os.name == 'nt' and sys.maxsize <= 2**32,
reason="OSError: symbolic link privilege not held")
def test_symlink_file(self, tmpdir):
long_name = 'a'*10 + self.filename

Expand Down
2 changes: 1 addition & 1 deletion testsuite/MDAnalysisTests/core/test_fragments.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def test_total_frags(self, u):
# number of unique fragindices must correspond to number of fragments:
assert len(np.unique(fragindices)) == len(fragments)
# check fragindices dtype:
assert fragindices.dtype == np.int64
assert fragindices.dtype == np.intp
#check n_fragments
assert u.atoms.n_fragments == len(fragments)

Expand Down
3 changes: 3 additions & 0 deletions testsuite/MDAnalysisTests/formats/test_libdcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from collections import namedtuple
import os
import sys
import string
import struct

Expand Down Expand Up @@ -316,6 +317,8 @@ def write_dcd(in_name, out_name, remarks='testing', header=None):
f_out.write(xyz=frame.xyz, box=frame.unitcell)


@pytest.mark.xfail(os.name == 'nt' and sys.maxsize <= 2**32,
reason="occasional fail on 32-bit windows")
@given(remarks=strategies.text(
alphabet=string.printable, min_size=0,
max_size=239)) # handle the printable ASCII strings
Expand Down
2 changes: 1 addition & 1 deletion testsuite/MDAnalysisTests/lib/test_augment.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ def test_undoaugment(b, qres):
q = apply_PBC(q, b)
aug, mapping = augment_coordinates(q, b, radius)
for idx, val in enumerate(aug):
imageid = np.asarray([len(q) + idx], dtype=np.int64)
imageid = np.asarray([len(q) + idx], dtype=np.intp)
assert_equal(mapping[idx], undo_augment(imageid, mapping, len(q))[0])
2 changes: 1 addition & 1 deletion testsuite/MDAnalysisTests/lib/test_cutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
[1, 2, 2, 6, 4, 4, ], # duplicates, non-monotonic
))
def test_unique_int_1d(values):
array = np.array(values, dtype=np.int64)
array = np.array(values, dtype=np.intp)
ref = np.unique(array)
res = unique_int_1d(array)
assert_equal(res, ref)
Expand Down
4 changes: 2 additions & 2 deletions testsuite/MDAnalysisTests/lib/test_distances.py
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ def test_output_type_capped_distance(self, incoords, min_cut, box, met,
else:
pairs = res
assert type(pairs) == np.ndarray
assert pairs.dtype.type == np.int64
assert pairs.dtype.type == np.intp
assert pairs.ndim == 2
assert pairs.shape[1] == 2
if ret_dist:
Expand All @@ -1270,7 +1270,7 @@ def test_output_type_self_capped_distance(self, incoords, min_cut, box,
else:
pairs = res
assert type(pairs) == np.ndarray
assert pairs.dtype.type == np.int64
assert pairs.dtype.type == np.intp
assert pairs.ndim == 2
assert pairs.shape[1] == 2
if ret_dist:
Expand Down
2 changes: 1 addition & 1 deletion testsuite/MDAnalysisTests/topology/test_tprparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def test_moltypes(self, top):
def test_molnums(self, top):
molnums = top.molnums.values
assert_equal(molnums, self.ref_molnums)
assert molnums.dtype == np.int64
assert molnums.dtype == np.intp
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While nobody likes changing unit tests to make them pass, I think the proposed approach (from Richard and maybe Lily?) for portability is that integer indexing will now be platform-sized rather than coerced to int64, so some tests will have platform-specific typing.



class TestTPR(TPRAttrs):
Expand Down