def unicode_charseq_strip(a, chars=None): if isinstance(a, types.UnicodeCharSeq): if is_nonelike(chars): def impl(a, chars=None): return str(a).strip() return impl elif isinstance(chars, types.UnicodeCharSeq): def impl(a, chars=None): return str(a).strip(str(chars)) return impl elif isinstance(chars, types.UnicodeType): def impl(a, chars=None): return str(a).strip(chars) return impl if isinstance(a, (types.CharSeq, types.Bytes)): if is_nonelike(chars): def impl(a, chars=None): return a._to_str().strip()._to_bytes() return impl elif isinstance(chars, (types.CharSeq, types.Bytes)): def impl(a, chars=None): return a._to_str().strip(chars._to_str())._to_bytes() return impl
def unicode_charseq_split(a, sep=None, maxsplit=-1): if not ( maxsplit == -1 or isinstance(maxsplit, (types.Omitted, types.Integer, types.IntegerLiteral)) ): return None if isinstance(a, types.UnicodeCharSeq): if isinstance(sep, types.UnicodeCharSeq): def impl(a, sep=None, maxsplit=-1): return str(a).split(sep=str(sep), maxsplit=maxsplit) return impl if isinstance(sep, types.UnicodeType): def impl(a, sep=None, maxsplit=-1): return str(a).split(sep=sep, maxsplit=maxsplit) return impl if is_nonelike(sep): if is_default(maxsplit, -1): def impl(a, sep=None, maxsplit=-1): return str(a).split() else: def impl(a, sep=None, maxsplit=-1): return str(a).split(maxsplit=maxsplit) return impl if isinstance(a, (types.CharSeq, types.Bytes)): if isinstance(sep, (types.CharSeq, types.Bytes)): def impl(a, sep=None, maxsplit=-1): return _map_bytes(a._to_str().split(sep._to_str(), maxsplit=maxsplit)) return impl if is_nonelike(sep): if is_default(maxsplit, -1): def impl(a, sep=None, maxsplit=-1): return _map_bytes(a._to_str().split()) else: def impl(a, sep=None, maxsplit=-1): return _map_bytes(a._to_str().split(maxsplit=maxsplit)) return impl
def ol_list_sort(lst, key=None, reverse=False): _sort_check_key(key) _sort_check_reverse(reverse) if cgutils.is_nonelike(key): KEY = False sort_f = sort_forwards sort_b = sort_backwards elif isinstance(key, types.Dispatcher): KEY = True sort_f = arg_sort_forwards sort_b = arg_sort_backwards def impl(lst, key=None, reverse=False): if KEY is True: _lst = [key(x) for x in lst] else: _lst = lst if reverse is False or reverse == 0: tmp = sort_f(_lst) else: tmp = sort_b(_lst) if KEY is True: lst[:] = [lst[i] for i in tmp] return impl
def wavedecn(data, wavelet, mode='symmetric', level=None, axis=None): have_axis = not is_nonelike(axis) def impl(data, wavelet, mode='symmetric', level=None, axis=None): if not have_axis: axis = List(range(data.ndim)) paxis = promote_axis(axis, data.ndim) naxis = len(paxis) # pmodes = promote_mode(mode, naxis) pwavelets = [discrete_wavelet(w) for w in promote_wavelets(wavelet, naxis)] dec_lens = [w.dec_hi.shape[0] for w in pwavelets] sizes = [data.shape[ax] for ax in paxis] plevel = promote_level(sizes, dec_lens, level) coeffs_list = List() a = data for i in range(plevel): coeffs = dwt(a, wavelet, mode, paxis) a = not_optional(coeffs.pop('a' * naxis)) coeffs_list.append(coeffs) coeffs_list.reverse() return a, coeffs_list return impl
def omnisci_buffer_get_ptr(x, index=None): if isinstance(x, BufferPointer): if cgutils.is_nonelike(index): def impl(x, index=None): return omnisci_buffer_ptr_get_ptr_(x) else: def impl(x, index=None): return omnisci_buffer_ptr_item_get_ptr_(x, index) return impl if isinstance(x, BufferType): if cgutils.is_nonelike(index): def impl(x, index=None): return omnisci_buffer_get_ptr_(x) else: raise NotImplementedError(f'omnisci_buffer_item_get_ptr_({x}, {index})') return impl
def _sort_check_key(key): if isinstance(key, types.Optional): msg = ("Key must concretely be None or a Numba JIT compiled function, " "an Optional (union of None and a value) was found") raise errors.TypingError(msg) if not (cgutils.is_nonelike(key) or isinstance(key, types.Dispatcher)): msg = "Key must be None or a Numba JIT compiled function" raise errors.TypingError(msg)
def omnisci_buffer_set_null(x, row_idx=None): if isinstance(x, BufferPointer): if cgutils.is_nonelike(row_idx): def impl(x, row_idx=None): return omnisci_buffer_set_null_(x) else: def impl(x, row_idx=None): return omnisci_array_set_null_(x, row_idx) return impl return impl
def omnisci_buffer_is_null(x, row_idx=None): T = x.eltype if isinstance(x, BufferPointer): if cgutils.is_nonelike(row_idx): def impl(x, row_idx=None): return omnisci_buffer_is_null_(x) else: def impl(x, row_idx=None): return omnisci_array_is_null_(T, x[row_idx]) return impl
def promote_level(sizes, dec_lens, level=None): have_level = not is_nonelike(level) if isinstance(sizes, nbtypes.Integer): int_sizes = True elif (isinstance(sizes, NUMBA_SEQUENCE_TYPES) and isinstance(sizes.dtype, nbtypes.Integer)): int_sizes = False else: raise TypeError("sizes must be an integer or " "sequence of integers") if isinstance(dec_lens, nbtypes.Integer): int_dec_len = True elif (isinstance(dec_lens, NUMBA_SEQUENCE_TYPES) and isinstance(dec_lens.dtype, nbtypes.Integer)): int_dec_len = False else: raise TypeError("dec_len must be an integer or " "sequence of integers") def impl(sizes, dec_lens, level=None): if int_sizes: sizes = List([sizes]) if int_dec_len: dec_lens = List([dec_lens]) max_level = min([dwt_max_level(s, d) for s, d in zip(sizes, dec_lens)]) if not have_level: level = max_level elif level < 0: raise ValueError("Negative levels are invalid. Minimum level is 0") elif level > max_level: # with numba.objmode(): # warnings.warn("Level value is too high. " # "All coefficients will experience " # "boundary effects") pass return level return impl
def ol_list_sort(lst, key=None, reverse=False): # The following is mostly borrowed from listobj.ol_list_sort from numba.typed import List listobj._sort_check_key(key) listobj._sort_check_reverse(reverse) if cgutils.is_nonelike(key): KEY = False sort_f = listobj.sort_forwards sort_b = listobj.sort_backwards elif isinstance(key, types.Dispatcher): KEY = True sort_f = listobj.arg_sort_forwards sort_b = listobj.arg_sort_backwards def impl(lst, key=None, reverse=False): if not lst._is_mutable(): raise ValueError("list is immutable") if KEY is True: # There's an unknown refct problem in reflected list. # Using an explicit loop with typedlist somehow "fixed" it. _lst = List() for x in lst: _lst.append(key(x)) else: _lst = lst if reverse is False or reverse == 0: tmp = sort_f(_lst) else: tmp = sort_b(_lst) if KEY is True: # There's an unknown refct problem in reflected list. # Using an explicit loop with typedlist somehow "fixed" it. ordered = List() for i in tmp: ordered.append(lst[i]) lst[:] = ordered return impl
def dwt(data, wavelet, mode="symmetric", axis=None): if isinstance(data, nbtypes.misc.Optional): if not isinstance(data.type, nbtypes.npytypes.Array): raise TypeError(f"data must be ndarray. Got {data.type}") elif not isinstance(data, nbtypes.npytypes.Array): raise TypeError(f"data must be an ndarray. Got {data}") have_axis = not is_nonelike(axis) def impl(data, wavelet, mode="symmetric", axis=None): if not have_axis: axis = List(range(data.ndim)) paxis = promote_axis(axis, data.ndim) naxis = len(paxis) pmode = promote_mode(mode, naxis) pwavelets = [discrete_wavelet(w) for w in promote_wavelets(wavelet, naxis)] coeffs = List([("", data)]) for a, (ax, m, wv) in enumerate(zip(paxis, pmode, pwavelets)): new_coeffs = List() for subband, x in coeffs: ca, cd = dwt_axis(x, wv, m, ax) new_coeffs.append((subband + "a", ca)) new_coeffs.append((subband + "d", cd)) coeffs = new_coeffs dict_coeffs = Dict() for name, coeff in coeffs: dict_coeffs[name] = coeff return dict_coeffs return impl
def waverecn(ca, coeffs, wavelet, mode='symmetric', axis=None): if not isinstance(ca, nbtypes.npytypes.Array): raise TypeError("ca must be an ndarray") have_axis = not is_nonelike(axis) ndim_slices = (slice(None),) * ca.ndim def impl(ca, coeffs, wavelet, mode='symmetric', axis=None): if len(coeffs) == 0: return ca coeff_ndims = [ca.ndim] coeff_shapes = [ca.shape] for c in coeffs: coeff_ndims.extend([v.ndim for v in c.values()]) coeff_shapes.extend([v.shape for v in c.values()]) unique_coeff_ndims = np.unique(np.array(coeff_ndims)) if len(unique_coeff_ndims) == 1: ndim = unique_coeff_ndims[0] else: raise ValueError("Coefficient dimensions don't match") if not have_axis: axis = List(range(ndim)) paxes = promote_axis(axis, ndim) naxis = len(paxes) for idx, c in enumerate(coeffs): c[not_optional('a' * naxis)] = ca ca = idwt(c, wavelet, mode, axis) return ca return impl
def idwt(coeffs, wavelet, mode='symmetric', axis=None): have_axis = not is_nonelike(axis) def impl(coeffs, wavelet, mode='symmetric', axis=None): ndim_transform = max([len(key) for key in coeffs.keys()]) coeff_shapes = [v.shape for v in coeffs.values()] if not have_axis: axis = List(range(ndim_transform)) ndim = ndim_transform else: ndim = len(coeff_shapes[0]) paxis = promote_axis(axis, ndim) naxis = len(paxis) pmode = promote_mode(mode, naxis) pwavelets = List([discrete_wavelet(w) for w in promote_wavelets(wavelet, naxis)]) it = list(enumerate(zip(paxis, pwavelets, pmode))) for key_length, (ax, wv, m) in it[::-1]: new_coeffs = {} new_keys = coeff_product('ad', key_length) for key in new_keys: L = coeffs[key + 'a'] H = coeffs[key + 'd'] new_coeffs[key] = idwt_axis(L, H, wv, m, ax) coeffs = new_coeffs return coeffs[''] return impl
def idwt_axis(approx_coeffs, detail_coeffs, wavelet, mode, axis): have_approx = not is_nonelike(approx_coeffs) have_detail = not is_nonelike(detail_coeffs) if not have_approx and not have_detail: raise ValueError("Either approximation or detail " "coefficients must be present") dtypes = [approx_coeffs.dtype if have_approx else None, detail_coeffs.dtype if have_detail else None] out_dtype = np.result_type(*(np.dtype(dt.name) for dt in dtypes if dt)) if have_approx and have_detail: if approx_coeffs.ndim != detail_coeffs.ndim: raise ValueError("approx_coeffs.ndim != detail_coeffs.ndim") def impl(approx_coeffs, detail_coeffs, wavelet, mode, axis): if have_approx and have_detail: coeff_shape = approx_coeffs.shape it = enumerate(zip(approx_coeffs.shape, detail_coeffs.shape)) # NOTE(sjperkins) # Clip the coefficient dimensions to the smallest dimensions # pywt clips in waverecn and fails in idwt and idwt_axis # on heterogenous coefficient shapes. # The actual clipping is performed in slice_axis for i, (asize, dsize) in it: size = asize if asize < dsize else dsize coeff_shape = tuple_setitem(coeff_shape, i, size) elif have_approx: coeff_shape = approx_coeffs.shape elif have_detail: coeff_shape = detail_coeffs.shape else: raise ValueError("Either approximation or detail must be present") if not (0 <= axis < len(coeff_shape)): raise ValueError(("0 <= axis < coeff.ndim does not hold")) idwt_len = idwt_buffer_length(coeff_shape[axis], wavelet.rec_lo.shape[0], mode) out_shape = tuple_setitem(coeff_shape, axis, idwt_len) output = np.empty(out_shape, dtype=out_dtype) # Iterate over all points except along the slicing axis for idx in np.ndindex(*tuple_setitem(output.shape, axis, 1)): initial_out_row = slice_axis(output, idx, axis, None) # Zero if we have a contiguous slice, else allocate if initial_out_row.flags.c_contiguous: out_row = force_type_contiguity(initial_out_row) out_row[:] = 0 else: out_row = np.zeros_like(initial_out_row) # Apply approximation coefficients if they exist if approx_coeffs is not None: initial_ca_row = slice_axis(approx_coeffs, idx, axis, coeff_shape[axis]) if initial_ca_row.flags.c_contiguous: ca_row = force_type_contiguity(initial_ca_row) else: ca_row = initial_ca_row.copy() upsampling_convolution_valid_sf(ca_row, wavelet.rec_lo, out_row, mode) # Apply detail coefficients if they exist if detail_coeffs is not None: initial_cd_row = slice_axis(detail_coeffs, idx, axis, coeff_shape[axis]) if initial_cd_row.flags.c_contiguous: cd_row = force_type_contiguity(initial_cd_row) else: cd_row = initial_cd_row.copy() upsampling_convolution_valid_sf(cd_row, wavelet.rec_hi, out_row, mode) # Copy back output row if the output space was non-contiguous if not initial_out_row.flags.c_contiguous: initial_out_row[:] = out_row return output return impl
def slice_axis(typingctx, array, index, axis, extent): if not isinstance(array, types.Array): raise TypeError("array is not an Array") if "C" not in array.layout: raise TypeError("array must be C contiguous") if (not isinstance(index, types.UniTuple) or not isinstance(index.dtype, types.Integer)): raise TypeError("index is not an Homogenous Tuple of Integers") if not isinstance(axis, types.Integer): raise TypeError("axis is not an Integer") have_extent = not cgutils.is_nonelike(extent) if have_extent and not isinstance(extent, types.Integer): raise TypeError("extent must be an integer or None") if len(index) != array.ndim: raise TypeError("array.ndim != len(index") # Return a single array, not necessarily contiguous return_type = array.copy(ndim=1, layout="A") sig = return_type(array, index, axis, extent) def codegen(context, builder, signature, args): array_type, idx_type, axis_type, extent_type = signature.args array, idx, axis, extent = args array = context.make_array(array_type)(context, builder, array) zero = context.get_constant(types.intp, 0) llvm_intp_t = context.get_value_type(types.intp) ndim = array_type.ndim view_shape = cgutils.alloca_once(builder, llvm_intp_t) view_stride = cgutils.alloca_once(builder, llvm_intp_t) # Final array indexes. We only know the slicing index at runtime # so we need to recreate idx but with zero at the slicing axis indices = cgutils.alloca_once(builder, llvm_intp_t, size=array_type.ndim) for ax in range(array_type.ndim): llvm_ax = context.get_constant(types.intp, ax) predicate = builder.icmp_unsigned("!=", llvm_ax, axis) with builder.if_else(predicate) as (not_equal, equal): with not_equal: # If this is not the slicing axis, # use the appropriate tuple index value = builder.extract_value(idx, ax) builder.store(value, builder.gep(indices, [llvm_ax])) with equal: # If this is the slicing axis, # store zero as the index. # Also record the stride and shape builder.store(zero, builder.gep(indices, [llvm_ax])) size = builder.extract_value(array.shape, ax) stride = builder.extract_value(array.strides, ax) if have_extent: ext_predicate = builder.icmp_signed(">=", extent, size) size = builder.select(ext_predicate, size, extent) builder.store(size, view_shape) builder.store(stride, view_stride) # Build a python list from indices tmp_indices = [] for i in range(ndim): i = context.get_constant(types.intp, i) tmp_indices.append(builder.load(builder.gep(indices, [i]))) # Get the data pointer obtained from indexing the array dataptr = cgutils.get_item_pointer(context, builder, array_type, array, tmp_indices, wraparound=True, boundscheck=True) # Set up the shape and stride. There'll only be one # dimension, corresponding to the axis along which we slice view_shapes = [builder.load(view_shape)] view_strides = [builder.load(view_stride)] # Make a view with the data pointer, shapes and strides retary = make_view(context, builder, array_type, array, return_type, dataptr, view_shapes, view_strides) result = retary._getvalue() return impl_ret_borrowed(context, builder, return_type, result) return sig, codegen
def waverecn(ca, coeffs, wavelet, mode='symmetric', axis=None): if not isinstance(ca, nbtypes.npytypes.Array): raise TypeError("ca must be an ndarray") have_axis = not is_nonelike(axis) ndim_slices = (slice(None),) * ca.ndim def impl(ca, coeffs, wavelet, mode='symmetric', axis=None): if len(coeffs) == 0: return ca coeff_ndims = [ca.ndim] coeff_shapes = [ca.shape] for c in coeffs: coeff_ndims.extend([v.ndim for v in c.values()]) coeff_shapes.extend([v.shape for v in c.values()]) unique_coeff_ndims = np.unique(np.array(coeff_ndims)) if len(unique_coeff_ndims) == 1: ndim = unique_coeff_ndims[0] else: raise ValueError("Coefficient dimensions don't match") if not have_axis: axis = List(range(ndim)) paxes = promote_axis(axis, ndim) naxis = len(paxes) for idx, c in enumerate(coeffs): c[not_optional('a' * naxis)] = ca ca = idwt(c, wavelet, mode, axis) return ca return impl # @numba.njit(nogil=True, fastmath=True, cache=True) # def ravel_coeffs(a_coeffs, coeffs): # ndim = a_coeffs.ndim # # initialize with the approximation coefficients. # a_size = a_coeffs.size # # preallocate output array # arr_size = a_size # n_coeffs = 0 # for d in coeffs: # n_coeffs += 1 # for k, v in d.items(): # arr_size += v.size # coeff_arr = np.empty((arr_size, ), dtype=a_coeffs.dtype) # a_slice = slice(a_size) # coeff_arr[a_slice] = a_coeffs.ravel() # # initialize list of coefficient slices # # coeff_slices = List() # # coeff_shapes = List() # # coeff_slices.append(a_slice) # # coeff_shapes.append(a_coeffs.shape) # # numba.typed.Dict(numba.types.unicode_type, numba.types.float64[:]) # # loop over the detail cofficients, embedding them in coeff_arr # offset = a_size # for coeff_dict in coeffs: # # new dictionaries for detail coefficient slices and shapes # # coeff_slices.append(Dict()) # # coeff_shapes.append(Dict()) # # sort to make sure key order is consistent across Python versions # keys = sorted(coeff_dict.keys()) # for i, key in enumerate(keys): # d = coeff_dict[key] # sl = slice(offset, offset + d.size) # offset += d.size # coeff_arr[sl] = d.ravel() # # coeff_slices[-1][key] = sl # # coeff_shapes[-1][key] = d.shape # return coeff_arr #, coeff_slices, coeff_shapes # @numba.njit(nogil=True, fastmath=True, cache=True) # def unravel_coeffs(arr, coeff_slices, coeff_shapes, output_format='wavedecn'): # arr = np.asarray(arr) # coeffs = List(arr[coeff_slices[0]].reshape(coeff_shapes[0])) # # difference coefficients at each level # for n in range(1, len(coeff_slices)): # slice_dict = coeff_slices[n] # shape_dict = coeff_shapes[n] # d = {} # for k, v in coeff_slices[n].items(): # d[k] = arr[v].reshape(shape_dict[k]) # coeffs.append(d) # return coeffs[0], coeffs[1:]