add append, insert, delete functions in numeric package

This commit is contained in:
wyq 2023-08-23 20:14:08 +08:00
parent ed90ae3529
commit ab15b26724
21 changed files with 694 additions and 92 deletions

View File

@ -331,7 +331,11 @@ public class MeshGraphic extends GraphicCollection3D {
vertexColor = new float[getVertexNumber() * 4]; vertexColor = new float[getVertexNumber() * 4];
float[] color; float[] color;
for (int i = 0; i < vertexValue.length; i++) { for (int i = 0; i < vertexValue.length; i++) {
color = legendScheme.findLegendBreak(vertexValue[i]).getColor().getRGBComponents(null); if (Float.isNaN(vertexValue[i])) {
color = legendScheme.getLegendBreak(0).getColor().getRGBComponents(null);
} else {
color = legendScheme.findLegendBreak(vertexValue[i]).getColor().getRGBComponents(null);
}
System.arraycopy(color, 0, vertexColor, i * 4, 4); System.arraycopy(color, 0, vertexColor, i * 4, 4);
} }
} }

View File

@ -67,7 +67,7 @@ import java.util.zip.ZipInputStream;
public static String getVersion(){ public static String getVersion(){
String version = GlobalUtil.class.getPackage().getImplementationVersion(); String version = GlobalUtil.class.getPackage().getImplementationVersion();
if (version == null || version.equals("")) { if (version == null || version.equals("")) {
version = "3.6.5"; version = "3.6.6";
} }
return version; return version;
} }

View File

@ -601,7 +601,7 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
Section section = new Section(origin, size, stride); Section section = new Section(origin, size, stride);
RadialRecord record = this.recordMap.get(varName); RadialRecord record = this.recordMap.get(varName);
Array dataArray = Array.factory(record.getDataType(), section.getShape()); Array dataArray = Array.factory(DataType.FLOAT, section.getShape());
Range zRange = section.getRange(0); Range zRange = section.getRange(0);
Range yRange = section.getRange(1); Range yRange = section.getRange(1);
Range xRange = section.getRange(2); Range xRange = section.getRange(2);
@ -623,36 +623,36 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
} }
} }
} }
}
Attribute aoAttr = variable.findAttribute("add_offset"); Attribute aoAttr = variable.findAttribute("add_offset");
Attribute sfAttr = variable.findAttribute("scale_factor"); Attribute sfAttr = variable.findAttribute("scale_factor");
if (aoAttr != null || sfAttr != null) { if (aoAttr != null || sfAttr != null) {
Number add_offset = 0.f; Number add_offset = 0.f;
Number scale_factor = 1.f; Number scale_factor = 1.f;
if (aoAttr != null) { if (aoAttr != null) {
switch (aoAttr.getDataType()) { switch (aoAttr.getDataType()) {
case DOUBLE: case DOUBLE:
add_offset = aoAttr.getValues().getDouble(0); add_offset = aoAttr.getValues().getDouble(0);
break; break;
case FLOAT: case FLOAT:
case INT: case INT:
add_offset = aoAttr.getValues().getFloat(0); add_offset = aoAttr.getValues().getFloat(0);
break; break;
}
} }
if (sfAttr != null) {
switch (sfAttr.getDataType()) {
case DOUBLE:
scale_factor = sfAttr.getValues().getDouble(0);
break;
case FLOAT:
case INT:
scale_factor = sfAttr.getValues().getFloat(0);
break;
}
}
dataArray = ArrayMath.div(ArrayMath.sub(dataArray, add_offset), scale_factor);
} }
if (sfAttr != null) {
switch (sfAttr.getDataType()) {
case DOUBLE:
scale_factor = sfAttr.getValues().getDouble(0);
break;
case FLOAT:
case INT:
scale_factor = sfAttr.getValues().getFloat(0);
break;
}
}
dataArray = ArrayMath.div(ArrayMath.sub(dataArray, add_offset), scale_factor);
} }
return dataArray; return dataArray;

View File

@ -8,27 +8,27 @@
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\no_opengl"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\no_opengl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array\complex"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\array\complex"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/>
</Path> </Path>
<File> <File>
<OpenedFiles> <OpenedFiles>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/> <OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/> <OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_geo.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_3d.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\array\gradient_1.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\array\delete_1.py"/>
</OpenedFiles> </OpenedFiles>
<RecentFiles> <RecentFiles>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/> <RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/> <RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_geo.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_3d.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\array\gradient_1.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\array\delete_1.py"/>
</RecentFiles> </RecentFiles>
</File> </File>
<Font> <Font>
@ -36,5 +36,5 @@
</Font> </Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/> <LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/> <Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1311,742"/> <Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo> </MeteoInfo>

View File

@ -26,9 +26,9 @@ class RadarDataFile(DimDataFile):
:return: Scan elevation angles. :return: Scan elevation angles.
""" """
if product is None: if product is None:
return list(self.datainfo.getElevations()) return np.array(self.datainfo.getElevations())
else: else:
return list(self.datainfo.getElevations(product)) return np.array(self.datainfo.getElevations(product))
def get_vcs_data(self, product, start_point, end_point): def get_vcs_data(self, product, start_point, end_point):
""" """

View File

@ -19,19 +19,43 @@ def antenna_to_cartesian(distance, azimuth, elevation, h=None):
""" """
azimuth = np.deg2rad(azimuth) azimuth = np.deg2rad(azimuth)
elevation = np.deg2rad(elevation) elevation = np.deg2rad(elevation)
nd = distance.shape[0] if azimuth.ndim == 1:
na = azimuth.shape[0] nd = distance.shape[0]
distance, azimuth = np.meshgrid(distance, azimuth) na = azimuth.shape[0]
if isinstance(elevation, np.NDArray): distance, azimuth = np.meshgrid(distance, azimuth)
elevation = elevation.reshape(na, 1) if isinstance(elevation, np.NDArray):
elevation = elevation.repeat(nd, axis=1) elevation = elevation.reshape(na, 1)
elevation = elevation._array elevation = elevation.repeat(nd, axis=1)
if h is None: elevation = elevation._array
r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation) if h is None:
else: r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation)
r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation, h) else:
r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation, h)
return np.array(r[0]), np.array(r[1]), np.array(r[2]) return np.array(r[0]), np.array(r[1]), np.array(r[2])
else:
nd = distance.shape[0]
ns, na = azimuth.shape
x = np.empty((ns, na, nd))
y = np.empty((ns, na, nd))
z = np.empty((ns,na,nd))
for i in range(ns):
dis, azi = np.meshgrid(distance, azimuth[i])
if elevation.ndim == 1:
ele = elevation[i]
else:
ele = elevation[i].reshape(na, 1).copy()
ele = ele.repeat(nd, axis=1)
ele = ele._array
if h is None:
r = Transform.antennaToCartesian(dis._array, azi._array, ele)
else:
r = Transform.antennaToCartesian(dis._array, azi._array, ele, h)
x[i] = np.array(r[0])
y[i] = np.array(r[1])
z[i] = np.array(r[2])
return x, y, z
def antenna_to_geographic(lon, lat, distance, azimuth, elevation, h=None): def antenna_to_geographic(lon, lat, distance, azimuth, elevation, h=None):
""" """

View File

@ -80,7 +80,10 @@ class NDArray(object):
return self.dtype.itemsize return self.dtype.itemsize
def __len__(self): def __len__(self):
return self._shape[0] if self.ndim == 0:
return 0
else:
return self._shape[0]
def __str__(self): def __str__(self):
return ArrayUtil.convertToString(self._array) return ArrayUtil.convertToString(self._array)
@ -296,10 +299,10 @@ class NDArray(object):
step = 1 step = 1
alllist = False alllist = False
elif isinstance(k, (list, tuple, NDArray)): elif isinstance(k, (list, tuple, NDArray)):
if isinstance(k, NDArray): if isinstance(k, (list, tuple)):
k = k.aslist() k = NDArray(k)
onlyrange = False onlyrange = False
ranges.append(k) ranges.append(k._array)
continue continue
else: else:
sidx = 0 if k.start is None else k.start sidx = 0 if k.start is None else k.start
@ -517,6 +520,32 @@ class NDArray(object):
else: else:
raise StopIteration() raise StopIteration()
def item(self, *args):
"""
Copy an element of an array to a standard Python scalar and return it.
:param args: none: in this case, the method only works for arrays with one element
(a.size == 1), which element is copied into a standard Python scalar object and returned.
int_type: this argument is interpreted as a flat index into the array, specifying which
element to copy and return.
tuple of int_types: functions as does a single int_type argument, except that the argument
is interpreted as a nd-index into the array.
:return: A copy of the specified element of the array as a suitable Python scalar
"""
if self.ndim == 0:
return self._array.get()
else:
index = self._array.getIndex()
if len(args) == 1:
if isinstance(args[0], int):
index.setCurrentIndex(args[0])
else:
index.set(args[0])
elif len(args) > 1:
index.set(args)
return self._array.getObject(index)
def copy(self): def copy(self):
""" """
Copy array values to a new array. Copy array values to a new array.

View File

@ -40,7 +40,7 @@ __all__ = [
'argmin','argmax','argsort','array','array_split','amax','amin','asanyarray','asarray','asgridarray', 'argmin','argmax','argsort','array','array_split','amax','amin','asanyarray','asarray','asgridarray',
'asgriddata','arcsin','asin','asmiarray','asstationdata','atleast_1d','atleast_2d','arctan','atan', 'asgriddata','arcsin','asin','asmiarray','asstationdata','atleast_1d','atleast_2d','arctan','atan',
'arctan2','atan2','ave_month','average','histogram','broadcast_to','cdiff','ceil', 'arctan2','atan2','ave_month','average','histogram','broadcast_to','cdiff','ceil',
'concatenate','conj','conjugate','corrcoef','cos','cosh','cylinder','degrees','delete','delnan','diag','diff', 'concatenate','conj','conjugate','corrcoef','cos','cosh','cylinder','degrees','delnan','diag','diff',
'datatable','dot','empty','empty_like','exp','eye','flatnonzero','floor', 'datatable','dot','empty','empty_like','exp','eye','flatnonzero','floor',
'fmax','fmin','full','hcurl','hdivg','hstack','hypot','identity','indices','interp2d','interpn','isarray', 'fmax','fmin','full','hcurl','hdivg','hstack','hypot','identity','indices','interp2d','interpn','isarray',
'isclose','isfinite','isinf','isnan','isscalar','linspace','log','log10','logical_not','logspace', 'isclose','isfinite','isinf','isnan','isscalar','linspace','log','log10','logical_not','logspace',
@ -65,7 +65,7 @@ def array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
:param dtype: (*DataType*) Data type :param dtype: (*DataType*) Data type
:param copy: (*bool*) If true (default), then the object is copied. :param copy: (*bool*) If true (default), then the object is copied.
:param order: (*str*) Specify the memory layout of the array. :param order: (*str*) Specify the memory layout of the array.
:param subok: (*bool*) If True, then sub-classes will be passed-through, :param subok: (*bool*) If True, then subclasses will be passed-through,
otherwise the returned array will be forced to be a base-class array (default). otherwise the returned array will be forced to be a base-class array (default).
:param ndmin: (*int*) Specifies the minimum number of dimensions that the :param ndmin: (*int*) Specifies the minimum number of dimensions that the
resulting array should have. resulting array should have.
@ -1753,8 +1753,8 @@ def argsort(a, axis=-1):
:param axis: (*int or None*) Optional. Axis along which to sort. If None, the array is :param axis: (*int or None*) Optional. Axis along which to sort. If None, the array is
flattened after sorting. The default is ``-1`` , which sorts along the last axis. flattened after sorting. The default is ``-1`` , which sorts along the last axis.
:returns: (*NDArray*) Array of indices that sort a along the specified axis. If a is :returns: (*NDArray*) Array of indices that sort `a` along the specified axis. If `a` is
one-dimensional, a[index_array] yields a sorted a. one-dimensional, a[index_array] yields a sorted `a`.
""" """
if isinstance(a, list): if isinstance(a, list):
a = array(a) a = array(a)
@ -1992,7 +1992,7 @@ def concatenate(arrays, axis=0):
""" """
ars = [] ars = []
for a in arrays: for a in arrays:
ars.append(a.asarray()) ars.append(asanyarray(a).asarray())
r = ArrayUtil.concatenate(ars, axis) r = ArrayUtil.concatenate(ars, axis)
return NDArray(r) return NDArray(r)
@ -2801,7 +2801,7 @@ def smooth5(x):
if isinstance(x, list): if isinstance(x, list):
x = array(x) x = array(x)
if x.ndim != 2: if x.ndim != 2:
print 'The array must be 2 dimension!' print('The array must be 2 dimension!')
raise ValueError() raise ValueError()
r = ArrayUtil.smooth5(x._array) r = ArrayUtil.smooth5(x._array)
if isinstance(x, DimArray): if isinstance(x, DimArray):
@ -2829,7 +2829,7 @@ def smooth9(x):
if isinstance(x, list): if isinstance(x, list):
x = array(x) x = array(x)
if x.ndim != 2: if x.ndim != 2:
print 'The array must be 2 dimension!' print('The array must be 2 dimension!')
raise ValueError() raise ValueError()
r = ArrayUtil.smooth9(x._array) r = ArrayUtil.smooth9(x._array)
if isinstance(x, DimArray): if isinstance(x, DimArray):

View File

@ -4,8 +4,10 @@ from ..core import dtype
from ..core._ndarray import NDArray from ..core._ndarray import NDArray
from ..core.fromnumeric import (ravel, nonzero) from ..core.fromnumeric import (ravel, nonzero)
from org.meteoinfo.ndarray.math import ArrayMath from org.meteoinfo.ndarray.math import ArrayMath
import warnings
__all__ = ['angle','extract', 'place', 'grid_edge', 'gradient'] __all__ = ['angle','extract', 'place', 'grid_edge', 'gradient', 'append',
'delete', 'insert']
def extract(condition, arr): def extract(condition, arr):
@ -365,4 +367,402 @@ def gradient(f, *varargs, **kwargs):
if len_axes == 1: if len_axes == 1:
return outvals[0] return outvals[0]
else: else:
return outvals return outvals
def append(arr, values, axis=None):
"""
Append values to the end of an array.
Parameters
----------
arr : array_like
Values are appended to a copy of this array.
values : array_like
These values are appended to a copy of `arr`. It must be of the
correct shape (the same shape as `arr`, excluding `axis`). If
`axis` is not specified, `values` can be any shape and will be
flattened before use.
axis : int, optional
The axis along which `values` are appended. If `axis` is not
given, both `arr` and `values` are flattened before use.
Returns
-------
append : ndarray
A copy of `arr` with `values` appended to `axis`. Note that
`append` does not occur in-place: a new array is allocated and
filled. If `axis` is None, `out` is a flattened array.
See Also
--------
insert : Insert elements into an array.
delete : Delete elements from an array.
Examples
--------
>>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
array([1, 2, 3, ..., 7, 8, 9])
When `axis` is specified, `values` must have the correct shape.
>>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0)
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
Traceback (most recent call last):
...
ValueError: all the input arrays must have same number of dimensions, but
the array at index 0 has 2 dimension(s) and the array at index 1 has 1
dimension(s)
"""
arr = np.asanyarray(arr)
if axis is None:
if arr.ndim != 1:
arr = arr.ravel()
values = ravel(values)
axis = arr.ndim-1
return np.concatenate((arr, values), axis=axis)
def delete(arr, obj, axis=None):
"""
Return a new array with sub-arrays along an axis deleted. For a one
dimensional array, this returns those entries not returned by
`arr[obj]`.
Parameters
----------
arr : array_like
Input array.
obj : slice, int or array of ints
Indicate indices of sub-arrays to remove along the specified axis.
.. versionchanged:: 1.19.0
Boolean indices are now treated as a mask of elements to remove,
rather than being cast to the integers 0 and 1.
axis : int, optional
The axis along which to delete the subarray defined by `obj`.
If `axis` is None, `obj` is applied to the flattened array.
Returns
-------
out : ndarray
A copy of `arr` with the elements specified by `obj` removed. Note
that `delete` does not occur in-place. If `axis` is None, `out` is
a flattened array.
See Also
--------
insert : Insert elements into an array.
append : Append elements at the end of an array.
Notes
-----
Often it is preferable to use a boolean mask. For example:
>>> arr = np.arange(12) + 1
>>> mask = np.ones(len(arr), dtype=bool)
>>> mask[[0,2,4]] = False
>>> result = arr[mask,...]
Is equivalent to ``np.delete(arr, [0,2,4], axis=0)``, but allows further
use of `mask`.
Examples
--------
>>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> arr
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> np.delete(arr, 1, 0)
array([[ 1, 2, 3, 4],
[ 9, 10, 11, 12]])
>>> np.delete(arr, np.s_[::2], 1)
array([[ 2, 4],
[ 6, 8],
[10, 12]])
>>> np.delete(arr, [1,3,5], None)
array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
"""
arr = np.asarray(arr)
ndim = arr.ndim
if axis is None:
if ndim != 1:
arr = arr.ravel()
# needed for np.matrix, which is still not 1d after being ravelled
ndim = arr.ndim
axis = ndim - 1
else:
axis = np.normalize_axis_index(axis, ndim)
slobj = [slice(None)]*ndim
N = arr.shape[axis]
newshape = list(arr.shape)
if isinstance(obj, slice):
start, stop, step = obj.indices(N)
xr = range(start, stop, step)
numtodel = len(xr)
if numtodel <= 0:
return arr.copy()
# Invert if step is negative:
if step < 0:
step = -step
start = xr[-1]
stop = xr[0] + 1
newshape[axis] -= numtodel
new = np.empty(newshape, arr.dtype)
# copy initial chunk
if start == 0:
pass
else:
slobj[axis] = slice(None, start)
new[tuple(slobj)] = arr[tuple(slobj)]
# copy end chunk
if stop == N:
pass
else:
slobj[axis] = slice(stop-numtodel, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(stop, None)
new[tuple(slobj)] = arr[tuple(slobj2)]
# copy middle pieces
if step == 1:
pass
else: # use array indexing.
keep = np.ones(stop-start, dtype=np.dtype.bool)
keep[:stop-start:step] = False
slobj[axis] = slice(start, stop-numtodel)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(start, stop)
arr = arr[tuple(slobj2)]
slobj2[axis] = keep
new[tuple(slobj)] = arr[tuple(slobj2)]
return new
if isinstance(obj, int) and not isinstance(obj, bool):
single_value = True
else:
single_value = False
_obj = obj
obj = np.asarray(obj)
# `size == 0` to allow empty lists similar to indexing, but (as there)
# is really too generic:
if obj.size == 0 and not isinstance(_obj, np.NDArray):
obj = obj.astype(np.dtype.int)
elif obj.size == 1 and obj.dtype.kind in "ui":
# For a size 1 integer array we can use the single-value path
# (most dtypes, except boolean, should just fail later).
obj = obj.item()
single_value = True
if single_value:
# optimization for a single value
if (obj < -N or obj >= N):
raise IndexError(
"index %i is out of bounds for axis %i with "
"size %i" % (obj, axis, N))
if (obj < 0):
obj += N
newshape[axis] -= 1
new = np.empty(newshape, arr.dtype,)
slobj[axis] = slice(None, obj)
new[tuple(slobj)] = arr[tuple(slobj)]
slobj[axis] = slice(obj, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(obj+1, None)
new[tuple(slobj)] = arr[tuple(slobj2)]
else:
if obj.dtype == np.dtype.bool:
if obj.shape != (N,):
raise ValueError('boolean array argument obj to delete '
'must be one dimensional and match the axis '
'length of {}'.format(N))
# optimization, the other branch is slower
keep = ~obj
else:
keep = np.ones(N, dtype=np.dtype.bool)
keep[obj,] = False
slobj[axis] = keep
new = arr[tuple(slobj)]
return new
def insert(arr, obj, values, axis=None):
"""
Insert values along the given axis before the given indices.
Parameters
----------
arr : array_like
Input array.
obj : int, slice or sequence of ints
Object that defines the index or indices before which `values` is
inserted.
Support for multiple insertions when `obj` is a single scalar or a
sequence with one element (similar to calling insert multiple
times).
values : array_like
Values to insert into `arr`. If the type of `values` is different
from that of `arr`, `values` is converted to the type of `arr`.
`values` should be shaped so that ``arr[...,obj,...] = values``
is legal.
axis : int, optional
Axis along which to insert `values`. If `axis` is None then `arr`
is flattened first.
Returns
-------
out : ndarray
A copy of `arr` with `values` inserted. Note that `insert`
does not occur in-place: a new array is returned. If
`axis` is None, `out` is a flattened array.
See Also
--------
append : Append elements at the end of an array.
concatenate : Join a sequence of arrays along an existing axis.
delete : Delete elements from an array.
Notes
-----
Note that for higher dimensional inserts ``obj=0`` behaves very different
from ``obj=[0]`` just like ``arr[:,0,:] = values`` is different from
``arr[:,[0],:] = values``.
Examples
--------
>>> a = np.array([[1, 1], [2, 2], [3, 3]])
>>> a
array([[1, 1],
[2, 2],
[3, 3]])
>>> np.insert(a, 1, 5)
array([1, 5, 1, ..., 2, 3, 3])
>>> np.insert(a, 1, 5, axis=1)
array([[1, 5, 1],
[2, 5, 2],
[3, 5, 3]])
Difference between sequence and scalars:
>>> np.insert(a, [1], [[1],[2],[3]], axis=1)
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
>>> np.array_equal(np.insert(a, 1, [1, 2, 3], axis=1),
... np.insert(a, [1], [[1],[2],[3]], axis=1))
True
>>> b = a.flatten()
>>> b
array([1, 1, 2, 2, 3, 3])
>>> np.insert(b, [2, 2], [5, 6])
array([1, 1, 5, ..., 2, 3, 3])
>>> np.insert(b, slice(2, 4), [5, 6])
array([1, 1, 5, ..., 2, 3, 3])
>>> np.insert(b, [2, 2], [7.13, False]) # type casting
array([1, 1, 7, ..., 2, 3, 3])
>>> x = np.arange(8).reshape(2, 4)
>>> idx = (1, 3)
>>> np.insert(x, idx, 999, axis=1)
array([[ 0, 999, 1, 2, 999, 3],
[ 4, 999, 5, 6, 999, 7]])
"""
arr = np.asarray(arr)
ndim = arr.ndim
if axis is None:
if ndim != 1:
arr = arr.ravel()
# needed for np.matrix, which is still not 1d after being ravelled
ndim = arr.ndim
axis = ndim - 1
else:
axis = np.normalize_axis_index(axis, ndim)
slobj = [slice(None)]*ndim
N = arr.shape[axis]
newshape = list(arr.shape)
if isinstance(obj, slice):
# turn it into a range object
indices = np.arange(*obj.indices(N), dtype=np.dtype.int)
else:
# need to copy obj, because indices will be changed in-place
indices = np.array(obj).copy()
if indices.dtype == np.dtype.bool:
# See also delete
warnings.warn(
"in the future insert will treat boolean arrays and "
"array-likes as a boolean index instead of casting it to "
"integer", FutureWarning, stacklevel=2)
indices = indices.astype(np.dtype.int)
elif indices.ndim > 1:
raise ValueError(
"index array argument obj to insert must be one dimensional "
"or scalar")
if indices.size == 1:
index = indices.item()
if index < -N or index > N:
raise IndexError("index {} is out of bounds for axis {} with size {}".
format(obj, axis, N))
if (index < 0):
index += N
# There are some object array corner cases here, but we cannot avoid
# that:
values = np.array(values, copy=False, ndmin=arr.ndim, dtype=arr.dtype)
if indices.ndim == 0:
# broadcasting is very different here, since a[:,0,:] = ... behaves
# very different from a[:,[0],:] = ...! This changes values so that
# it works likes the second case. (here a[:,0:1,:])
values = np.moveaxis(values, 0, axis)
numnew = values.shape[axis]
newshape[axis] += numnew
new = np.empty(newshape, arr.dtype,)
slobj[axis] = slice(None, index)
new[tuple(slobj)] = arr[tuple(slobj)]
slobj[axis] = slice(index, index+numnew)
new[tuple(slobj)] = values
slobj[axis] = slice(index+numnew, None)
slobj2 = [slice(None)] * ndim
slobj2[axis] = slice(index, None)
new[tuple(slobj)] = arr[tuple(slobj2)]
return new
elif indices.size == 0 and not isinstance(obj, np.NDArray):
# Can safely cast the empty list to intp
indices = indices.astype(np.dtype.int)
indices[indices < 0] += N
numnew = len(indices)
#order = indices.argsort(kind='mergesort') # stable sort
order = np.argsort(indices)
indices[order] += np.arange(numnew)
newshape[axis] += numnew
old_mask = np.ones(newshape[axis], dtype=np.dtype.bool)
old_mask[indices] = False
new = np.empty(newshape, arr.dtype)
slobj2 = [slice(None)]*ndim
slobj[axis] = indices
slobj2[axis] = old_mask
new[tuple(slobj)] = values
new[tuple(slobj2)] = arr
return new

View File

@ -183,8 +183,12 @@ def getcolors(cs, alpha=None):
if isinstance(cs[0], int): if isinstance(cs[0], int):
colors.append(getcolor(cs, alpha)) colors.append(getcolor(cs, alpha))
else: else:
for c in cs: if isinstance(alpha, (tuple, list)):
colors.append(getcolor(c, alpha)) for c, a in zip(cs, alpha):
colors.append(getcolor(c, a))
else:
for c in cs:
colors.append(getcolor(c, alpha))
else: else:
colors.append(getcolor(cs, alpha)) colors.append(getcolor(cs, alpha))
return colors return colors

View File

@ -0,0 +1,53 @@
package org.meteoinfo.math.sort;
import java.util.Arrays;
public class MergeSort {
/**
* Merge sort
* @param sourceArray Source array
* @return Sorted array
* @throws Exception
*/
public int[] sort(int[] sourceArray) throws Exception {
// arr 进行拷贝不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
if (arr.length < 2) {
return arr;
}
int middle = (int) Math.floor(arr.length / 2);
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
return merge(sort(left), sort(right));
}
protected int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
int i = 0;
while (left.length > 0 && right.length > 0) {
if (left[0] <= right[0]) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
} else {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
}
while (left.length > 0) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
}
while (right.length > 0) {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
return result;
}
}

View File

@ -45,7 +45,7 @@ import java.util.Comparator;
* always appear before S in the sorted list. * always appear before S in the sorted list.
* <p> * <p>
* For speed of execution, we implement it without recursion. Instead, * For speed of execution, we implement it without recursion. Instead,
* we requires an auxiliary array (stack) of storage, of length * we require an auxiliary array (stack) of storage, of length
* 2 log<sub><small>2</small></sub> n. When a subarray has gotten down to size 7, * 2 log<sub><small>2</small></sub> n. When a subarray has gotten down to size 7,
* we sort it by straight insertion. * we sort it by straight insertion.
* *

View File

@ -305,7 +305,11 @@ public class ArrayBoolean extends Array {
} }
public void setObject(Index i, Object value) { public void setObject(Index i, Object value) {
storage[i.currentElement()] = (Boolean) value; if (value instanceof Integer) {
storage[i.currentElement()] = ((Integer) value == 1);
} else {
storage[i.currentElement()] = (Boolean) value;
}
} }
// package private : mostly for iterators // package private : mostly for iterators

View File

@ -275,7 +275,11 @@ public class ArrayDouble extends Array {
} }
public void setObject(Index i, Object value) { public void setObject(Index i, Object value) {
storageD[i.currentElement()] = ((Number) value).doubleValue(); if (value instanceof Boolean) {
storageD[i.currentElement()] = ((Boolean) value) ? 1 : 0;
} else {
storageD[i.currentElement()] = ((Number) value).doubleValue();
}
} }
// trusted, assumes that individual dimension lengths have been checked // trusted, assumes that individual dimension lengths have been checked
@ -368,7 +372,11 @@ public class ArrayDouble extends Array {
} }
public void setObject(int index, Object value) { public void setObject(int index, Object value) {
storageD[index] = ((Number) value).doubleValue(); if (value instanceof Boolean) {
storageD[index] = ((Boolean) value) ? 1 : 0;
} else {
storageD[index] = ((Number) value).doubleValue();
}
} }
/** /**

View File

@ -298,7 +298,11 @@ public class ArrayInt extends Array {
} }
public void setObject(Index i, Object value) { public void setObject(Index i, Object value) {
storage[i.currentElement()] = ((Number) value).intValue(); if (value instanceof Boolean) {
storage[i.currentElement()] = ((Boolean) value) ? 1 : 0;
} else {
storage[i.currentElement()] = ((Number) value).intValue();
}
} }
// package private : mostly for iterators // package private : mostly for iterators
@ -397,7 +401,11 @@ public class ArrayInt extends Array {
} }
public void setObject(int index, Object value) { public void setObject(int index, Object value) {
storage[index] = ((Number) value).intValue(); if (value instanceof Boolean) {
storage[index] = ((Boolean) value) ? 1 : 0;
} else {
storage[index] = ((Number) value).intValue();
}
} }
/** /**

View File

@ -672,6 +672,18 @@ public class Index implements Cloneable {
return this; return this;
} }
/**
* Set the current element's index. General-rank case.
*
* @param index set current value to these values
* @return this, so you can use A.get(i.set(i))
* @throws ArrayIndexOutOfBoundsException if index.length != rank.
*/
public Index set(List<Integer> indexList) {
int[] index = indexList.stream().mapToInt(Integer::intValue).toArray();
return set(index);
}
/** /**
* set current element at dimension dim to v * set current element at dimension dim to v
* *

View File

@ -1,6 +1,9 @@
package org.meteoinfo.ndarray; package org.meteoinfo.ndarray;
import org.meteoinfo.ndarray.math.ArrayUtil;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class MixIterator implements IndexIterator { public class MixIterator implements IndexIterator {
@ -29,7 +32,21 @@ public class MixIterator implements IndexIterator {
if (range instanceof Range) { if (range instanceof Range) {
shape[i] = ((Range) range).length(); shape[i] = ((Range) range).length();
} else { } else {
shape[i] = ((List) range).size(); Array arr = (Array) range;
if (arr.getDataType() == DataType.BOOLEAN) {
List<Integer> tList = new ArrayList<>();
IndexIterator iter = arr.getIndexIterator();
int j = 0;
while (iter.hasNext()) {
if (iter.getBooleanNext()) {
tList.add(j);
}
j += 1;
}
arr = ArrayUtil.array_list(tList, DataType.INT);
this.ranges.set(i, arr);
}
shape[i] = (int) arr.getSize();
} }
i += 1; i += 1;
} }
@ -297,9 +314,9 @@ public class MixIterator implements IndexIterator {
int c; int c;
for (Object range : this.ranges) { for (Object range : this.ranges) {
if (range instanceof Range) { if (range instanceof Range) {
c = ((Range)range).elementNC(rangeCounter[i]); c = ((Range) range).elementNC(rangeCounter[i]);
} else { } else {
c = ((List<Integer>)range).get(rangeCounter[i]); c = ((Array) range).getInt(rangeCounter[i]);
} }
currentCounter[i] = c; currentCounter[i] = c;
i += 1; i += 1;

View File

@ -6022,11 +6022,11 @@ public class ArrayMath {
public static Array setSection(Array a, List<Range> ranges, Array v) throws InvalidRangeException { public static Array setSection(Array a, List<Range> ranges, Array v) throws InvalidRangeException {
Array r = a.section(ranges); Array r = a.section(ranges);
IndexIterator iter = r.getIndexIterator(); IndexIterator iter = r.getIndexIterator();
if (r.getSize() != v.getSize()) { /*if (r.getSize() != v.getSize()) {
if (r.getShape() != v.getShape()) { if (r.getShape() != v.getShape()) {
v = ArrayUtil.broadcast(v, r.getShape()); v = ArrayUtil.broadcast(v, r.getShape());
} }
} }*/
Index index = v.getIndex(); Index index = v.getIndex();
while (iter.hasNext()) { while (iter.hasNext()) {
iter.setObjectNext(v.getObject(index)); iter.setObjectNext(v.getObject(index));
@ -6207,18 +6207,34 @@ public class ArrayMath {
* @param v Number value * @param v Number value
* @return Result array * @return Result array
*/ */
public static Array setSection_List(Array a, List<List<Integer>> ranges, Number v) { public static Array setSection_List(Array a, List<Array> ranges, Number v) {
//Array r = copy(a); //Array r = copy(a);
int n = a.getRank(); int n = a.getRank();
int[] count = new int[n]; int[] count = new int[n];
Index index = a.getIndex(); Index index = a.getIndex();
int m = ranges.get(0).size(); int m = (int) ranges.get(0).getSize();
for (int i = 0; i < m; i++) { if (ranges.get(0).getDataType() == DataType.BOOLEAN) {
for (int j = 0; j < n; j++) { for (int i = 0; i < m; i++) {
count[j] = ranges.get(j).get(i); boolean bool = true;
for (int j = 0; j < n; j++) {
if (!ranges.get(j).getBoolean(i)) {
bool = false;
break;
}
}
if (bool) {
a.setObject(index, v);
}
index.incr();
}
} else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
count[j] = ranges.get(j).getInt(i);
}
index.set(count);
a.setObject(index, v);
} }
index.set(count);
a.setObject(index, v);
} }
return a; return a;
@ -6232,20 +6248,37 @@ public class ArrayMath {
* @param v Array value * @param v Array value
* @return Result array * @return Result array
*/ */
public static Array setSection_List(Array a, List<List<Integer>> ranges, Array v) { public static Array setSection_List(Array a, List<Array> ranges, Array v) {
//Array r = copy(a); //Array r = copy(a);
int n = a.getRank(); int n = a.getRank();
int[] count = new int[n]; int[] count = new int[n];
Index index = a.getIndex(); Index index = a.getIndex();
Index vIndex = v.getIndex(); Index vIndex = v.getIndex();
int m = ranges.get(0).size(); int m = (int) ranges.get(0).getSize();
for (int i = 0; i < m; i++) { if (ranges.get(0).getDataType() == DataType.BOOLEAN) {
for (int j = 0; j < n; j++) { for (int i = 0; i < m; i++) {
count[j] = ranges.get(j).get(i); boolean bool = true;
for (int j = 0; j < n; j++) {
if (!ranges.get(j).getBoolean(i)) {
bool = false;
break;
}
}
if (bool) {
a.setObject(index, v.getObject(vIndex));
vIndex.incr();
}
index.incr();
}
} else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
count[j] = ranges.get(j).getInt(i);
}
index.set(count);
a.setObject(index, v.getObject(vIndex));
vIndex.incr();
} }
index.set(count);
a.setObject(index, v.getObject(vIndex));
vIndex.incr();
} }
return a; return a;

View File

@ -1633,6 +1633,12 @@ public class ArrayUtil {
StringBuilder sbuff = new StringBuilder(); StringBuilder sbuff = new StringBuilder();
sbuff.append("array("); sbuff.append("array(");
int ndim = a.getRank(); int ndim = a.getRank();
if (ndim == 0) {
sbuff.append(a.getObject(0));
sbuff.append(")");
return sbuff.toString();
}
if (ndim > 1) { if (ndim > 1) {
for (int i = 0; i < ndim - 1; i++) for (int i = 0; i < ndim - 1; i++)
sbuff.append("["); sbuff.append("[");