diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 9bceff5..1093e9f 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,10 +1,20 @@ 0.6.12 ---------- +Enhancements + + - use stable sort in histogram + Bug Fixes - Fixed bug in inverting WCS to map ra,dec to x,y near ra = 0 (Matt Becker) + - fix splitarray corner cases + +Comapatibility + + - update for numpy 2 (Eli Rykoff) + - update to new scipy usage for scipy.integrate.cumulative_trapezoid v0.6.11 -------------------------- diff --git a/esutil/coords.py b/esutil/coords.py index f0be76f..807cc64 100644 --- a/esutil/coords.py +++ b/esutil/coords.py @@ -519,9 +519,9 @@ def xyz2eq(xin, yin, zin, units="deg", stomp=False): if set to True, use the stomp convention. """ - x = np.array(xin, ndmin=1, copy=False) - y = np.array(yin, ndmin=1, copy=False) - z = np.array(zin, ndmin=1, copy=False) + x = np.atleast_1d(xin) + y = np.atleast_1d(yin) + z = np.atleast_1d(zin) theta, phi = _xyz2thetaphi(x, y, z) if stomp: @@ -1242,8 +1242,8 @@ def rotate(phi, theta, psi, ra, dec): else: is_scalar = True - ra = np.array(ra, ndmin=1, copy=False) - dec = np.array(dec, ndmin=1, copy=False) + ra = np.atleast_1d(ra) + dec = np.atleast_1d(dec) if ra.size != dec.size: raise ValueError( "ra[%d] has different size than " "dec[%d]" % (ra.size, dec.size) diff --git a/esutil/cosmology/cosmology.py b/esutil/cosmology/cosmology.py index 7dbbcdf..5d5f844 100644 --- a/esutil/cosmology/cosmology.py +++ b/esutil/cosmology/cosmology.py @@ -172,18 +172,18 @@ def Dc(self, zmin, zmax): elif not isscalar(zmin) and isscalar(zmax): # scalar for zmin, array for zmax - zmin = np.array(zmin, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) d = self._cosmo.Dc_vec1(zmin, zmax) elif isscalar(zmin) and not isscalar(zmax): # array for zmin, scalar zmax - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmax = _as_c_order(zmax) d = self._cosmo.Dc_vec2(zmin, zmax) elif not isscalar(zmin) and not isscalar(zmax): # both arrays: must be same length - zmin = np.array(zmin, dtype="f8", copy=False, order="C") - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) + zmax = _as_c_order(zmax) if len(zmin) != len(zmax): raise ValueError( "If zmin and zmax are arrays, they must be same length" @@ -223,18 +223,18 @@ def Dm(self, zmin, zmax): elif not isscalar(zmin) and isscalar(zmax): # scalar for zmin, array for zmax - zmin = np.array(zmin, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) d = self._cosmo.Dm_vec1(zmin, zmax) elif isscalar(zmin) and not isscalar(zmax): # array for zmin, scalar zmax - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmax = _as_c_order(zmax) d = self._cosmo.Dm_vec2(zmin, zmax) elif not isscalar(zmin) and not isscalar(zmax): # both arrays: must be same length - zmin = np.array(zmin, dtype="f8", copy=False, order="C") - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) + zmax = _as_c_order(zmax) if len(zmin) != len(zmax): raise ValueError( "If zmin and zmax are arrays, they must be same length" @@ -271,18 +271,18 @@ def Da(self, zmin, zmax): elif not isscalar(zmin) and isscalar(zmax): # scalar for zmin, array for zmax - zmin = np.array(zmin, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) d = self._cosmo.Da_vec1(zmin, zmax) elif isscalar(zmin) and not isscalar(zmax): # array for zmin, scalar zmax - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmax = _as_c_order(zmax) d = self._cosmo.Da_vec2(zmin, zmax) elif not isscalar(zmin) and not isscalar(zmax): # both arrays: must be same length - zmin = np.array(zmin, dtype="f8", copy=False, order="C") - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) + zmax = _as_c_order(zmax) if len(zmin) != len(zmax): raise ValueError( "If zmin and zmax are arrays, they must be same length" @@ -318,18 +318,18 @@ def Dl(self, zmin, zmax): elif not isscalar(zmin) and isscalar(zmax): # scalar for zmin, array for zmax - zmin = np.array(zmin, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) d = self._cosmo.Dl_vec1(zmin, zmax) elif isscalar(zmin) and not isscalar(zmax): # array for zmin, scalar zmax - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmax = _as_c_order(zmax) d = self._cosmo.Dl_vec2(zmin, zmax) elif not isscalar(zmin) and not isscalar(zmax): # both arrays: must be same length - zmin = np.array(zmin, dtype="f8", copy=False, order="C") - zmax = np.array(zmax, dtype="f8", copy=False, order="C") + zmin = _as_c_order(zmin) + zmax = _as_c_order(zmax) if len(zmin) != len(zmax): raise ValueError( "If zmin and zmax are arrays, they must be same length" @@ -355,7 +355,7 @@ def dV(self, z): if isscalar(z): dv = self._cosmo.dV(z) else: - z = np.array(z, dtype="f8", copy=False, order="C") + z = _as_c_order(z) dv = self._cosmo.dV_vec(z) return dv @@ -412,18 +412,18 @@ def sigmacritinv(self, zl, zs): elif not isscalar(zl) and isscalar(zs): # scalar for zl, array for zs - zl = np.array(zl, dtype="f8", copy=False, order="C") + zl = _as_c_order(zl) scinv = self._cosmo.scinv_vec1(zl, zs) elif isscalar(zl) and not isscalar(zs): # array for zl, scalar zs - zs = np.array(zs, dtype="f8", copy=False, order="C") + zs = _as_c_order(zs) scinv = self._cosmo.scinv_vec2(zl, zs) elif not isscalar(zl) and not isscalar(zs): # both arrays: must be same length - zl = np.array(zl, dtype="f8", copy=False, order="C") - zs = np.array(zs, dtype="f8", copy=False, order="C") + zl = _as_c_order(zl) + zs = _as_c_order(zs) if len(zl) != len(zs): raise ValueError( "If zl and zs are arrays, they must be same length", @@ -452,7 +452,7 @@ def Ez_inverse(self, z): if isscalar(z): ez = self._cosmo.ez_inverse(z) else: - z = np.array(z, dtype="f8", copy=False, order="C") + z = _as_c_order(z) ez = self._cosmo.ez_inverse_vec(z) return ez @@ -750,3 +750,7 @@ def test_vs_purepy(self, ntime=0): print("C code:", tm) print("pure py code:", tmpy) print("C code is", tmpy / tm, "faster") + + +def _as_c_order(arr): + return np.atleast_1d(np.asarray(arr, dtype='f8', order='C')) diff --git a/esutil/cosmology_purepy.py b/esutil/cosmology_purepy.py index ef8d9b1..3faf6a3 100644 --- a/esutil/cosmology_purepy.py +++ b/esutil/cosmology_purepy.py @@ -201,8 +201,8 @@ def Dc(self, z1in, z2in): """ # Make sure they are arrays, but don't copy if already an array - z1 = numpy.array(z1in, ndmin=1, copy=False) - z2 = numpy.array(z2in, ndmin=1, copy=False) + z1 = numpy.atleast_1d(z1in) + z2 = numpy.atleast_1d(z2in) # All the permutations of inputs dh = self.DH() @@ -295,8 +295,8 @@ def Da(self, zmin, zmax): 3) Two arrays of the same length. """ - z1 = numpy.array(zmin, ndmin=1, copy=False) - z2 = numpy.array(zmax, ndmin=1, copy=False) + z1 = numpy.atleast_1d(zmin) + z2 = numpy.atleast_1d(zmax) d = self.Dm(z1, z2) da = numpy.where(z1 < z2, d / (1.0 + z2), d / (1.0 + z1)) @@ -327,8 +327,8 @@ def Dl(self, zmin, zmax): 3) Two arrays of the same length. """ - z1 = numpy.array(zmin, ndmin=1, copy=False) - z2 = numpy.array(zmax, ndmin=1, copy=False) + z1 = numpy.atleast_1d(zmin) + z2 = numpy.atleast_1d(zmax) return self.Da(z1, z2) * (1.0 + z2) ** 2 def distmod(self, z): @@ -377,7 +377,7 @@ def dV(self, z_input, comoving=True): comoving=True: Use comoving coords, default True. """ - z = numpy.array(z_input, ndmin=1, copy=False) + z = numpy.atleast_1d(z_input) dh = self.DH() da = self.Da(0.0, z) @@ -419,7 +419,7 @@ def V(self, zmin, zmax, comoving=True): ezivals = self.dV(zvals, comoving=comoving) v = f1 * ((ezivals * self.vwwi).sum()) - v = numpy.array(v, ndmin=1) + v = numpy.atleast_1d(v) return v def extract_parms(self, omega_m, omega_l, omega_k, flat): @@ -460,7 +460,7 @@ def Ez_inverse(self, z): ezi = cosmo.Ez_inverse(z) """ if not isscalar(z): - z = numpy.array(z, copy=False) + z = numpy.array(z) arg = ( self.omega_m * (1.0 + z) ** 3 + self.omega_k * (1.0 + z) ** 2 + self.omega_l # noqa ) @@ -510,8 +510,8 @@ def sigmacritinv(self, zl, zs): """ - zl = numpy.array(zl, ndmin=1, copy=False) - zs = numpy.array(zs, ndmin=1, copy=False) + zl = numpy.atleast_1d(zl) + zs = numpy.atleast_1d(zs) if (zl.size != 1) and (zs.size != 1): if zl.size != zs.size: @@ -694,8 +694,8 @@ def Dc(z1in, z2in, ) # Make sure they are arrays, but don't copy if already an array - z1 = numpy.array(z1in, ndmin=1, copy=False) - z2 = numpy.array(z2in, ndmin=1, copy=False) + z1 = numpy.atleast_1d(z1in) + z2 = numpy.atleast_1d(z2in) # All the permutations of inputs dh = DH(h=h) @@ -799,8 +799,8 @@ def Da(zmin, zmax, npts: Number of points in the integration. Default 5, good to 1.e-8 to redshift 1. """ - z1 = numpy.array(zmin, ndmin=1, copy=False) - z2 = numpy.array(zmax, ndmin=1, copy=False) + z1 = numpy.atleast_1d(zmin) + z2 = numpy.atleast_1d(zmax) d = Dm(z1, z2, omega_m, omega_l, omega_k, h=h, flat=flat, npts=npts) da = numpy.where(z1 < z2, d / (1.0 + z2), d / (1.0 + z1)) diff --git a/esutil/htm/htm.py b/esutil/htm/htm.py index 1c822b6..699a14c 100644 --- a/esutil/htm/htm.py +++ b/esutil/htm/htm.py @@ -73,8 +73,8 @@ def lookup_id(self, ra, dec): The htm index """ - ra = np.array(ra, dtype="f8", ndmin=1, copy=False) - dec = np.array(dec, dtype="f8", ndmin=1, copy=False) + ra = np.atleast_1d(ra).astype('f8') + dec = np.atleast_1d(dec).astype('f8') if ra.size != dec.size: raise ValueError("ra and dec must be the same size") @@ -215,11 +215,11 @@ def match( """ - ra1 = np.array(ra1, dtype="f8", ndmin=1, copy=False) - dec1 = np.array(dec1, dtype="f8", ndmin=1, copy=False) - ra2 = np.array(ra2, dtype="f8", ndmin=1, copy=False) - dec2 = np.array(dec2, dtype="f8", ndmin=1, copy=False) - radius = np.array(radius, dtype="f8", ndmin=1, copy=False) + ra1 = np.atleast_1d(ra1).astype('f8') + dec1 = np.atleast_1d(dec1).astype('f8') + ra2 = np.atleast_1d(ra2).astype('f8') + dec2 = np.atleast_1d(dec2).astype('f8') + radius = np.atleast_1d(radius).astype('f8') if ra1.size != dec1.size or ra2.size != ra2.size: stup = (ra1.size, dec1.size, ra2.size, dec2.size) @@ -405,16 +405,16 @@ def cylmatch( Added to HTM class in July 2010. """ - ra1 = np.array(ra1, dtype="f8", ndmin=1, copy=False) - dec1 = np.array(dec1, dtype="f8", ndmin=1, copy=False) - z1 = np.array(z1, dtype="f8", ndmin=1, copy=False) + ra1 = np.atleast_1d(ra1).astype('f8') + dec1 = np.atleast_1d(dec1).astype('f8') + z1 = np.atleast_1d(z1).astype('f8') - ra2 = np.array(ra2, dtype="f8", ndmin=1, copy=False) - dec2 = np.array(dec2, dtype="f8", ndmin=1, copy=False) - z2 = np.array(z2, dtype="f8", ndmin=1, copy=False) + ra2 = np.atleast_1d(ra2).astype('f8') + dec2 = np.atleast_1d(dec2).astype('f8') + z2 = np.atleast_1d(z2).astype('f8') - radius = np.array(radius, dtype="f8", ndmin=1, copy=False) - dz = np.array(dz, dtype="f8", ndmin=1, copy=False) + radius = np.atleast_1d(radius).astype('f8') + dz = np.atleast_1d(dz).astype('f8') npts = ra1.size npts2 = ra2.size @@ -684,10 +684,10 @@ def bincount( else: verb = 0 - ra1 = np.array(ra1, dtype="f8", ndmin=1, copy=False) - dec1 = np.array(dec1, dtype="f8", ndmin=1, copy=False) - ra2 = np.array(ra2, dtype="f8", ndmin=1, copy=False) - dec2 = np.array(dec2, dtype="f8", ndmin=1, copy=False) + ra1 = np.atleast_1d(ra1).astype('f8') + dec1 = np.atleast_1d(dec1).astype('f8') + ra2 = np.atleast_1d(ra2).astype('f8') + dec2 = np.atleast_1d(dec2).astype('f8') if ra1.size != dec1.size or ra2.size != ra2.size: stup = (ra1.size, dec1.size, ra2.size, dec2.size) @@ -698,7 +698,7 @@ def bincount( ) if scale is not None: - scale = np.array(scale, dtype="f8", ndmin=1, copy=False) + scale = np.atleast_1d(scale).astype('f8') if scale.size != 1 and scale.size != ra1.size: raise ValueError( "scale size (%d) != 1 and" @@ -710,7 +710,7 @@ def bincount( minid = htmid2.min() maxid = htmid2.max() else: - htmid2 = np.array(htmid2, dtype="i8", ndmin=1, copy=False) + htmid2 = np.atleast_1d(htmid2).astype('i8') if htmid2.size != ra2.size: raise ValueError( "htmid2 size %d != " "ra size %d" % (htmid2.size, ra2.size) @@ -759,8 +759,8 @@ class Matcher(htmc.Matcher): def __init__(self, depth, ra, dec): - ra = np.array(ra, dtype="f8", ndmin=1, copy=False) - dec = np.array(dec, dtype="f8", ndmin=1, copy=False) + ra = np.atleast_1d(ra).astype('f8') + dec = np.atleast_1d(dec).astype('f8') if ra.size != dec.size: raise ValueError( @@ -815,9 +815,9 @@ def match(self, ra, dec, radius, maxmatch=1, file=None): if file= is sent then then number of matches is returned. """ - ra = np.array(ra, dtype="f8", ndmin=1, copy=False) - dec = np.array(dec, dtype="f8", ndmin=1, copy=False) - radius = np.array(radius, dtype="f8", ndmin=1, copy=False) + ra = np.atleast_1d(ra).astype('f8') + dec = np.atleast_1d(dec).astype('f8') + radius = np.atleast_1d(radius).astype('f8') if ra.size != dec.size: raise ValueError( diff --git a/esutil/numpy_util.py b/esutil/numpy_util.py index f63e2e7..608a9cf 100644 --- a/esutil/numpy_util.py +++ b/esutil/numpy_util.py @@ -1533,8 +1533,8 @@ def match(arr1input, arr2input, presorted=False): """ # make sure 1D - arr1 = np.array(arr1input, ndmin=1, copy=False) - arr2 = np.array(arr2input, ndmin=1, copy=False) + arr1 = np.atleast_1d(arr1input) + arr2 = np.atleast_1d(arr2input) # check for integer data... if not issubclass(arr1.dtype.type, np.integer) or not issubclass( @@ -1815,7 +1815,7 @@ def splitarray(nper, var_input): """ - var = np.array(var_input, ndmin=1, copy=False) + var = np.atleast_1d(var_input) nchunks = var.size // nper if var.size % nper != 0: nchunks += 1 diff --git a/esutil/plotting.py b/esutil/plotting.py index 18a8316..33579dc 100644 --- a/esutil/plotting.py +++ b/esutil/plotting.py @@ -726,10 +726,10 @@ def bwhiskers( if "aspect_ratio" in keys: plt.aspect_ratio = keys["aspect_ratio"] - x = np.array(xin, copy=False, ndmin=1) - y = np.array(yin, copy=False, ndmin=1) - u = np.array(uin, copy=False, ndmin=1) - v = np.array(vin, copy=False, ndmin=1) + x = np.atleast_1d(xin) + y = np.atleast_1d(yin) + u = np.atleast_1d(uin) + v = np.atleast_1d(vin) if x.size != y.size or x.size != u.size or x.size != v.size: raise ValueError( @@ -921,10 +921,10 @@ def mwhiskers( """ - x = np.array(xin, copy=False, ndmin=1) - y = np.array(yin, copy=False, ndmin=1) - u = np.array(uin, copy=False, ndmin=1) - v = np.array(vin, copy=False, ndmin=1) + x = np.atleast_1d(xin) + y = np.atleast_1d(yin) + u = np.atleast_1d(uin) + v = np.atleast_1d(vin) if x.size != y.size or x.size != u.size or x.size != v.size: raise ValueError( @@ -962,8 +962,8 @@ def plotrand(x, y, frac=0.1, get_indices=False, **keys): plot a random subset of the points """ - x = np.array(x, ndmin=1, copy=False) - y = np.array(y, ndmin=1, copy=False) + x = np.atleast_1d(x) + y = np.atleast_1d(y) if x.size != y.size: raise ValueError("x,y must be same size") nrand = int(x.size * frac) @@ -1029,7 +1029,7 @@ def transform_box(lonmin, lonmax, latmin, latmax, fromsys, tosys, **keys): def asinh_scale(image, alpha=0.02, nonlinearity=8.0): - image_out = np.array(image, dtype="f8", copy=True) + image_out = image.copy().astype('f8') image_out[:] = np.arcsinh(alpha * nonlinearity * image) / nonlinearity @@ -1037,7 +1037,7 @@ def asinh_scale(image, alpha=0.02, nonlinearity=8.0): def image_norm(image, reverse=False): - image_out = np.array(image, dtype="f8", copy=True) + image_out = image.copy().astype('f8') image_out /= image_out.max() if reverse: diff --git a/esutil/random.py b/esutil/random.py index 33849cb..5effba7 100644 --- a/esutil/random.py +++ b/esutil/random.py @@ -165,7 +165,7 @@ def __init__( ) x = numpy.linspace(xrange[0], xrange[1], nx) - self.xinput = numpy.array(x, ndmin=1, copy=False) + self.xinput = numpy.atleast_1d(x) # input is some type of function self.isfunc = True @@ -179,11 +179,11 @@ def __init__( "corresponding x values" ) - self.xinput = numpy.array(x, ndmin=1, copy=False) + self.xinput = numpy.atleast_1d(x) # points were entered self.isfunc = False - self.pofx = numpy.array(pofx, ndmin=1, copy=False) + self.pofx = numpy.atleast_1d(pofx) if self.xinput.shape != self.pofx.shape: raise ValueError("x and pofx must be same shape") diff --git a/esutil/recfile/Util.py b/esutil/recfile/Util.py index d1b2345..55eb5a3 100644 --- a/esutil/recfile/Util.py +++ b/esutil/recfile/Util.py @@ -323,8 +323,7 @@ def get_colnums(self, colnames): get the column number for the input column name """ - colnames = numpy.array(colnames, ndmin=1, copy=False) - + colnames = numpy.atleast_1d(colnames) colnums = numpy.zeros(colnames.size, dtype="i8") for i in range(colnames.size): @@ -680,7 +679,7 @@ def _get_rows2read(self, rows): return None try: # a sequence entered - rows2read = numpy.array(rows, ndmin=1, copy=False, dtype="i8") + rows2read = numpy.atleast_1d(rows).astype("i8") if rows2read.size == 1: rows2read[0] = self._fix_range(rows2read[0], isslice=False) except Exception: diff --git a/esutil/recfile/records.hpp b/esutil/recfile/records.hpp index f1f5709..1e9ccbf 100644 --- a/esutil/recfile/records.hpp +++ b/esutil/recfile/records.hpp @@ -14,11 +14,11 @@ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION // Numpy 1/2 compatibility shims -#ifndef PyDataType_ELSIZE -#define PyDataType_ELSIZE(descr) descr->elsize -#define PyDataType_NAMES(descr) descr->names -#define PyDataType_FIELDS(descr) descr->fields -#define PyDataType_SUBARRAY(descr) descr->subarray +#if NPY_ABI_VERSION < 0x02000000 +#define PyDataType_ELSIZE(descr) ((descr)->elsize) +#define PyDataType_NAMES(descr) ((descr)->names) +#define PyDataType_FIELDS(descr) ((descr)->fields) +#define PyDataType_SUBARRAY(descr) ((descr)->subarray) #endif using namespace std; diff --git a/setup.py b/setup.py index 7b081cf..24370cd 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ import os from glob import glob -import platform import tempfile import subprocess import shutil