diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java
index e510ddeb..1ce5ccd7 100644
--- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java
@@ -331,7 +331,11 @@ public class MeshGraphic extends GraphicCollection3D {
vertexColor = new float[getVertexNumber() * 4];
float[] color;
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);
}
}
diff --git a/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java
index a0d13ed0..ba8b1783 100644
--- a/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java
+++ b/meteoinfo-common/src/main/java/org/meteoinfo/common/util/GlobalUtil.java
@@ -67,7 +67,7 @@ import java.util.zip.ZipInputStream;
public static String getVersion(){
String version = GlobalUtil.class.getPackage().getImplementationVersion();
if (version == null || version.equals("")) {
- version = "3.6.5";
+ version = "3.6.6";
}
return version;
}
diff --git a/meteoinfo-data/src/main/java/org/meteoinfo/data/meteodata/radar/CMARadarBaseDataInfo.java b/meteoinfo-data/src/main/java/org/meteoinfo/data/meteodata/radar/CMARadarBaseDataInfo.java
index bc1d8426..14c4e213 100644
--- a/meteoinfo-data/src/main/java/org/meteoinfo/data/meteodata/radar/CMARadarBaseDataInfo.java
+++ b/meteoinfo-data/src/main/java/org/meteoinfo/data/meteodata/radar/CMARadarBaseDataInfo.java
@@ -601,7 +601,7 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
Section section = new Section(origin, size, stride);
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 yRange = section.getRange(1);
Range xRange = section.getRange(2);
@@ -623,36 +623,36 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
}
}
}
+ }
- Attribute aoAttr = variable.findAttribute("add_offset");
- Attribute sfAttr = variable.findAttribute("scale_factor");
- if (aoAttr != null || sfAttr != null) {
- Number add_offset = 0.f;
- Number scale_factor = 1.f;
- if (aoAttr != null) {
- switch (aoAttr.getDataType()) {
- case DOUBLE:
- add_offset = aoAttr.getValues().getDouble(0);
- break;
- case FLOAT:
- case INT:
- add_offset = aoAttr.getValues().getFloat(0);
- break;
- }
+ Attribute aoAttr = variable.findAttribute("add_offset");
+ Attribute sfAttr = variable.findAttribute("scale_factor");
+ if (aoAttr != null || sfAttr != null) {
+ Number add_offset = 0.f;
+ Number scale_factor = 1.f;
+ if (aoAttr != null) {
+ switch (aoAttr.getDataType()) {
+ case DOUBLE:
+ add_offset = aoAttr.getValues().getDouble(0);
+ break;
+ case FLOAT:
+ case INT:
+ add_offset = aoAttr.getValues().getFloat(0);
+ 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;
diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml
index 063f604e..d53f7b24 100644
--- a/meteoinfo-lab/milconfig.xml
+++ b/meteoinfo-lab/milconfig.xml
@@ -8,27 +8,27 @@
-
-
+
+
-
-
+
+
-
-
+
+
@@ -36,5 +36,5 @@
-
+
diff --git a/meteoinfo-lab/pylib/mipylib/dataset/radardatafile.py b/meteoinfo-lab/pylib/mipylib/dataset/radardatafile.py
index 5aae4ce1..7dee2641 100644
--- a/meteoinfo-lab/pylib/mipylib/dataset/radardatafile.py
+++ b/meteoinfo-lab/pylib/mipylib/dataset/radardatafile.py
@@ -26,9 +26,9 @@ class RadarDataFile(DimDataFile):
:return: Scan elevation angles.
"""
if product is None:
- return list(self.datainfo.getElevations())
+ return np.array(self.datainfo.getElevations())
else:
- return list(self.datainfo.getElevations(product))
+ return np.array(self.datainfo.getElevations(product))
def get_vcs_data(self, product, start_point, end_point):
"""
diff --git a/meteoinfo-lab/pylib/mipylib/dataset/util/RadarUtil.py b/meteoinfo-lab/pylib/mipylib/dataset/util/RadarUtil.py
index ed33f2c2..bf6c5e95 100644
--- a/meteoinfo-lab/pylib/mipylib/dataset/util/RadarUtil.py
+++ b/meteoinfo-lab/pylib/mipylib/dataset/util/RadarUtil.py
@@ -19,19 +19,43 @@ def antenna_to_cartesian(distance, azimuth, elevation, h=None):
"""
azimuth = np.deg2rad(azimuth)
elevation = np.deg2rad(elevation)
- nd = distance.shape[0]
- na = azimuth.shape[0]
- distance, azimuth = np.meshgrid(distance, azimuth)
- if isinstance(elevation, np.NDArray):
- elevation = elevation.reshape(na, 1)
- elevation = elevation.repeat(nd, axis=1)
- elevation = elevation._array
- if h is None:
- r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation)
- else:
- r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation, h)
+ if azimuth.ndim == 1:
+ nd = distance.shape[0]
+ na = azimuth.shape[0]
+ distance, azimuth = np.meshgrid(distance, azimuth)
+ if isinstance(elevation, np.NDArray):
+ elevation = elevation.reshape(na, 1)
+ elevation = elevation.repeat(nd, axis=1)
+ elevation = elevation._array
+ if h is None:
+ r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation)
+ 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):
"""
diff --git a/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py b/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py
index 63e9671a..e75c20c7 100644
--- a/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py
+++ b/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py
@@ -80,7 +80,10 @@ class NDArray(object):
return self.dtype.itemsize
def __len__(self):
- return self._shape[0]
+ if self.ndim == 0:
+ return 0
+ else:
+ return self._shape[0]
def __str__(self):
return ArrayUtil.convertToString(self._array)
@@ -296,10 +299,10 @@ class NDArray(object):
step = 1
alllist = False
elif isinstance(k, (list, tuple, NDArray)):
- if isinstance(k, NDArray):
- k = k.aslist()
+ if isinstance(k, (list, tuple)):
+ k = NDArray(k)
onlyrange = False
- ranges.append(k)
+ ranges.append(k._array)
continue
else:
sidx = 0 if k.start is None else k.start
@@ -517,6 +520,32 @@ class NDArray(object):
else:
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):
"""
Copy array values to a new array.
diff --git a/meteoinfo-lab/pylib/mipylib/numeric/core/numeric$py.class b/meteoinfo-lab/pylib/mipylib/numeric/core/numeric$py.class
index 5c4d87ea..87a34db8 100644
Binary files a/meteoinfo-lab/pylib/mipylib/numeric/core/numeric$py.class and b/meteoinfo-lab/pylib/mipylib/numeric/core/numeric$py.class differ
diff --git a/meteoinfo-lab/pylib/mipylib/numeric/core/numeric.py b/meteoinfo-lab/pylib/mipylib/numeric/core/numeric.py
index cfbd8bc8..36bb5ddd 100644
--- a/meteoinfo-lab/pylib/mipylib/numeric/core/numeric.py
+++ b/meteoinfo-lab/pylib/mipylib/numeric/core/numeric.py
@@ -40,7 +40,7 @@ __all__ = [
'argmin','argmax','argsort','array','array_split','amax','amin','asanyarray','asarray','asgridarray',
'asgriddata','arcsin','asin','asmiarray','asstationdata','atleast_1d','atleast_2d','arctan','atan',
'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',
'fmax','fmin','full','hcurl','hdivg','hstack','hypot','identity','indices','interp2d','interpn','isarray',
'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 copy: (*bool*) If true (default), then the object is copied.
: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).
:param ndmin: (*int*) Specifies the minimum number of dimensions that the
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
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
- one-dimensional, a[index_array] yields a sorted a.
+ :returns: (*NDArray*) Array of indices that sort `a` along the specified axis. If `a` is
+ one-dimensional, a[index_array] yields a sorted `a`.
"""
if isinstance(a, list):
a = array(a)
@@ -1992,7 +1992,7 @@ def concatenate(arrays, axis=0):
"""
ars = []
for a in arrays:
- ars.append(a.asarray())
+ ars.append(asanyarray(a).asarray())
r = ArrayUtil.concatenate(ars, axis)
return NDArray(r)
@@ -2801,7 +2801,7 @@ def smooth5(x):
if isinstance(x, list):
x = array(x)
if x.ndim != 2:
- print 'The array must be 2 dimension!'
+ print('The array must be 2 dimension!')
raise ValueError()
r = ArrayUtil.smooth5(x._array)
if isinstance(x, DimArray):
@@ -2829,7 +2829,7 @@ def smooth9(x):
if isinstance(x, list):
x = array(x)
if x.ndim != 2:
- print 'The array must be 2 dimension!'
+ print('The array must be 2 dimension!')
raise ValueError()
r = ArrayUtil.smooth9(x._array)
if isinstance(x, DimArray):
diff --git a/meteoinfo-lab/pylib/mipylib/numeric/lib/function_base.py b/meteoinfo-lab/pylib/mipylib/numeric/lib/function_base.py
index e8a17e20..0f4427e3 100644
--- a/meteoinfo-lab/pylib/mipylib/numeric/lib/function_base.py
+++ b/meteoinfo-lab/pylib/mipylib/numeric/lib/function_base.py
@@ -4,8 +4,10 @@ from ..core import dtype
from ..core._ndarray import NDArray
from ..core.fromnumeric import (ravel, nonzero)
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):
@@ -365,4 +367,402 @@ def gradient(f, *varargs, **kwargs):
if len_axes == 1:
return outvals[0]
else:
- return outvals
\ No newline at end of file
+ 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
diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class
index 4ae7e94b..7631d86c 100644
Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class differ
diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py
index c7cf4614..3ece26d2 100644
--- a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py
+++ b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py
@@ -183,8 +183,12 @@ def getcolors(cs, alpha=None):
if isinstance(cs[0], int):
colors.append(getcolor(cs, alpha))
else:
- for c in cs:
- colors.append(getcolor(c, alpha))
+ if isinstance(alpha, (tuple, list)):
+ for c, a in zip(cs, alpha):
+ colors.append(getcolor(c, a))
+ else:
+ for c in cs:
+ colors.append(getcolor(c, alpha))
else:
colors.append(getcolor(cs, alpha))
return colors
diff --git a/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/MergeSort.java b/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/MergeSort.java
new file mode 100644
index 00000000..c68351f3
--- /dev/null
+++ b/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/MergeSort.java
@@ -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;
+ }
+}
diff --git a/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/QuickSort.java b/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/QuickSort.java
index a2265f64..5ba540df 100644
--- a/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/QuickSort.java
+++ b/meteoinfo-math/src/main/java/org/meteoinfo/math/sort/QuickSort.java
@@ -45,7 +45,7 @@ import java.util.Comparator;
* always appear before S in the sorted list.
*
* 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 log2 n. When a subarray has gotten down to size 7,
* we sort it by straight insertion.
*
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
index c9e252db..7a1907cd 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
@@ -305,7 +305,11 @@ public class ArrayBoolean extends Array {
}
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
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
index 9262c99d..a21c5a8d 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
@@ -275,7 +275,11 @@ public class ArrayDouble extends Array {
}
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
@@ -368,7 +372,11 @@ public class ArrayDouble extends Array {
}
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();
+ }
}
/**
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
index 294778f1..68e439ea 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
@@ -298,7 +298,11 @@ public class ArrayInt extends Array {
}
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
@@ -397,7 +401,11 @@ public class ArrayInt extends Array {
}
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();
+ }
}
/**
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index.java
index 95fab67f..e896fd66 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index.java
@@ -672,6 +672,18 @@ public class Index implements Cloneable {
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 indexList) {
+ int[] index = indexList.stream().mapToInt(Integer::intValue).toArray();
+ return set(index);
+ }
+
/**
* set current element at dimension dim to v
*
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MixIterator.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MixIterator.java
index a3a58679..70e1dd7f 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MixIterator.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MixIterator.java
@@ -1,6 +1,9 @@
package org.meteoinfo.ndarray;
+import org.meteoinfo.ndarray.math.ArrayUtil;
+
import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.List;
public class MixIterator implements IndexIterator {
@@ -29,7 +32,21 @@ public class MixIterator implements IndexIterator {
if (range instanceof Range) {
shape[i] = ((Range) range).length();
} else {
- shape[i] = ((List) range).size();
+ Array arr = (Array) range;
+ if (arr.getDataType() == DataType.BOOLEAN) {
+ List 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;
}
@@ -297,9 +314,9 @@ public class MixIterator implements IndexIterator {
int c;
for (Object range : this.ranges) {
if (range instanceof Range) {
- c = ((Range)range).elementNC(rangeCounter[i]);
+ c = ((Range) range).elementNC(rangeCounter[i]);
} else {
- c = ((List)range).get(rangeCounter[i]);
+ c = ((Array) range).getInt(rangeCounter[i]);
}
currentCounter[i] = c;
i += 1;
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayMath.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayMath.java
index eaceb98d..2a011aa2 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayMath.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayMath.java
@@ -6022,11 +6022,11 @@ public class ArrayMath {
public static Array setSection(Array a, List ranges, Array v) throws InvalidRangeException {
Array r = a.section(ranges);
IndexIterator iter = r.getIndexIterator();
- if (r.getSize() != v.getSize()) {
+ /*if (r.getSize() != v.getSize()) {
if (r.getShape() != v.getShape()) {
v = ArrayUtil.broadcast(v, r.getShape());
}
- }
+ }*/
Index index = v.getIndex();
while (iter.hasNext()) {
iter.setObjectNext(v.getObject(index));
@@ -6207,18 +6207,34 @@ public class ArrayMath {
* @param v Number value
* @return Result array
*/
- public static Array setSection_List(Array a, List> ranges, Number v) {
+ public static Array setSection_List(Array a, List ranges, Number v) {
//Array r = copy(a);
int n = a.getRank();
int[] count = new int[n];
Index index = a.getIndex();
- int m = ranges.get(0).size();
- for (int i = 0; i < m; i++) {
- for (int j = 0; j < n; j++) {
- count[j] = ranges.get(j).get(i);
+ int m = (int) ranges.get(0).getSize();
+ if (ranges.get(0).getDataType() == DataType.BOOLEAN) {
+ for (int i = 0; i < m; 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;
@@ -6232,20 +6248,37 @@ public class ArrayMath {
* @param v Array value
* @return Result array
*/
- public static Array setSection_List(Array a, List> ranges, Array v) {
+ public static Array setSection_List(Array a, List ranges, Array v) {
//Array r = copy(a);
int n = a.getRank();
int[] count = new int[n];
Index index = a.getIndex();
Index vIndex = v.getIndex();
- int m = ranges.get(0).size();
- for (int i = 0; i < m; i++) {
- for (int j = 0; j < n; j++) {
- count[j] = ranges.get(j).get(i);
+ int m = (int) ranges.get(0).getSize();
+ if (ranges.get(0).getDataType() == DataType.BOOLEAN) {
+ for (int i = 0; i < m; 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;
diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java
index 91541f41..cb43b3a8 100644
--- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java
@@ -1633,6 +1633,12 @@ public class ArrayUtil {
StringBuilder sbuff = new StringBuilder();
sbuff.append("array(");
int ndim = a.getRank();
+ if (ndim == 0) {
+ sbuff.append(a.getObject(0));
+ sbuff.append(")");
+ return sbuff.toString();
+ }
+
if (ndim > 1) {
for (int i = 0; i < ndim - 1; i++)
sbuff.append("[");