Merge branch 'master' into spectrogram

This commit is contained in:
Zoltán Vörös 2022-02-01 20:29:53 +01:00 committed by GitHub
commit ae9604db21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 208 additions and 68 deletions

View file

@ -775,7 +775,7 @@ ndarray_obj_t *ndarray_copy_view_convert_type(ndarray_obj_t *source, uint8_t dty
if((source->dtype == NDARRAY_FLOAT) && (dtype != NDARRAY_FLOAT)) {
// floats must be treated separately, because they can't directly be converted to integer types
mp_float_t f = ndarray_get_float_value(sarray, source->dtype);
item = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(floor)(f));
item = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(f));
} else {
item = mp_binary_get_val_array(source->dtype, sarray, 0);
}

View file

@ -8,6 +8,7 @@
* Copyright (c) 2022 Zoltán Vörös
*/
#include <math.h>
#include <string.h>
#include "py/builtin.h"
@ -236,6 +237,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(io_load_obj, io_load);
#endif /* ULAB_NUMPY_HAS_LOAD */
#if ULAB_NUMPY_HAS_LOADTXT
static void io_assign_value(const char *clipboard, uint8_t len, ndarray_obj_t *ndarray, size_t *idx, uint8_t dtype) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
if(dtype != NDARRAY_FLOAT) {
mp_float_t _value = mp_obj_get_float(value);
value = mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(_value));
}
ndarray_set_value(dtype, ndarray->array, (*idx)++, value);
}
static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
@ -243,6 +253,8 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
{ MP_QSTR_comments, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_max_rows, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } },
{ MP_QSTR_usecols, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } },
{ MP_QSTR_dtype, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = NDARRAY_FLOAT } },
{ MP_QSTR_skiprows, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@ -275,9 +287,10 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
comment_char = _comment_char[0];
}
uint16_t skiprows = args[6].u_int;
uint16_t max_rows = ULAB_IO_MAX_ROWS;
if((args[3].u_int > 0) && (args[3].u_int < ULAB_IO_MAX_ROWS)) {
max_rows = args[3].u_int;
max_rows = args[3].u_int + skiprows;
}
uint16_t *cols = NULL;
@ -304,6 +317,8 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
}
}
uint8_t dtype = args[5].u_int;
// count the columns and rows
// we actually count only the rows and the items, and assume that
// the number of columns can be gotten by means of a simple division,
@ -311,6 +326,7 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
char *offset;
uint16_t rows = 0, items = 0, all_rows = 0;
uint8_t read;
uint8_t len = 0;
do {
read = (uint8_t)stream_p->read(stream, buffer, ULAB_IO_BUFFER_SIZE - 1, &error);
@ -331,9 +347,12 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
// catch whitespaces here: if these are not on a comment line, then they delimit a number
if(*offset == '\n') {
rows++;
all_rows++;
items++;
if(all_rows > skiprows) {
rows++;
items++;
len = 0;
}
if(all_rows == max_rows) {
break;
}
@ -345,13 +364,22 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
while((*offset == ' ') || (*offset == '\t') || (*offset == '\v') || (*offset == '\f') || (*offset == '\r')) {
offset++;
}
items++;
if(len > 0) {
if(all_rows >= skiprows) {
items++;
}
len = 0;
}
} else {
offset++;
len++;
}
}
} while((read > 0) && (all_rows < max_rows));
if(rows == 0) {
mp_raise_ValueError(translate("empty file"));
}
uint16_t columns = items / rows;
if(columns < used_columns) {
@ -363,7 +391,7 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
#if ULAB_MAX_DIMS == 1
shape[0] = rows;
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(1, shape, NDARRAY_FLOAT);
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(1, shape, dtype);
#else
if(args[4].u_obj == mp_const_none) {
shape[ULAB_MAX_DIMS - 1] = columns;
@ -371,11 +399,9 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
shape[ULAB_MAX_DIMS - 1] = used_columns;
}
shape[ULAB_MAX_DIMS - 2] = rows;
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(2, shape, NDARRAY_FLOAT);
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(2, shape, dtype);
#endif
mp_float_t *array = (mp_float_t *)ndarray->array;
struct mp_stream_seek_t seek_s;
seek_s.offset = 0;
seek_s.whence = MP_SEEK_SET;
@ -383,11 +409,12 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
char *clipboard = m_new(char, ULAB_IO_CLIPBOARD_SIZE);
char *clipboard_origin = clipboard;
uint8_t len = 0;
rows = 0;
columns = 0;
len = 0;
size_t idx = 0;
do {
read = stream_p->read(stream, buffer, ULAB_IO_BUFFER_SIZE - 1, &error);
buffer[read] = '\0';
@ -406,40 +433,43 @@ static mp_obj_t io_loadtxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
}
}
if(rows == max_rows) {
break;
}
if((*offset == ' ') || (*offset == '\t') || (*offset == '\v') ||
(*offset == '\f') || (*offset == '\r') || (*offset == '\n') || (*offset == delimiter)) {
offset++;
while((*offset == ' ') || (*offset == '\t') || (*offset == '\v') || (*offset == '\f') || (*offset == '\r') || (*offset == '\n')) {
while((*offset == ' ') || (*offset == '\t') || (*offset == '\v') ||
(*offset == '\f') || (*offset == '\r') || (*offset == '\n')) {
offset++;
}
clipboard = clipboard_origin;
#if ULAB_MAX_DIMS == 1
if(columns == cols[0]) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
*array++ = mp_obj_get_float(value);
}
#else
if(args[4].u_obj == mp_const_none) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
*array++ = mp_obj_get_float(value);
} else {
for(uint8_t c = 0; c < used_columns; c++) {
if(columns == cols[c]) {
mp_obj_t value = mp_parse_num_decimal(clipboard, len, false, false, NULL);
*array++ = mp_obj_get_float(value);
break;
if(len > 0) {
clipboard = clipboard_origin;
if(rows >= skiprows) {
#if ULAB_MAX_DIMS == 1
if(columns == cols[0]) {
io_assign_value(clipboard, len, ndarray, &idx, dtype);
}
#else
if(args[4].u_obj == mp_const_none) {
io_assign_value(clipboard, len, ndarray, &idx, dtype);
} else {
for(uint8_t c = 0; c < used_columns; c++) {
if(columns == cols[c]) {
io_assign_value(clipboard, len, ndarray, &idx, dtype);
break;
}
}
}
#endif
}
}
#endif
columns++;
len = 0;
columns++;
len = 0;
if(offset[-1] == '\n') {
columns = 0;
rows++;
if(rows == max_rows) {
break;
if(offset[-1] == '\n') {
columns = 0;
rows++;
}
}
} else {
@ -721,7 +751,7 @@ static mp_obj_t io_savetxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
const char *comments = mp_obj_str_get_data(args[5].u_obj, &_len);
stream_p->write(stream, comments, _len, &error);
} else {
stream_p->write(stream, "#", 1, &error);
stream_p->write(stream, "# ", 2, &error);
}
const char *header = mp_obj_str_get_data(args[3].u_obj, &_len);
stream_p->write(stream, header, _len, &error);
@ -769,7 +799,7 @@ static mp_obj_t io_savetxt(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
const char *comments = mp_obj_str_get_data(args[5].u_obj, &_len);
stream_p->write(stream, comments, _len, &error);
} else {
stream_p->write(stream, "#", 1, &error);
stream_p->write(stream, "# ", 2, &error);
}
const char *footer = mp_obj_str_get_data(args[4].u_obj, &_len);
stream_p->write(stream, footer, _len, &error);

View file

@ -435,22 +435,22 @@ static mp_obj_t linalg_qr(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_
// [[c s],
// [s -c]]
if(MICROPY_FLOAT_C_FUN(fabs)(rarray[i * n + j]) < LINALG_EPSILON) { // r[i, j]
c = (rarray[(i - 1) * n + j] >= 0.0) ? 1.0 : -1.0; // r[i-1, j]
c = (rarray[(i - 1) * n + j] >= MICROPY_FLOAT_CONST(0.0)) ? MICROPY_FLOAT_CONST(1.0) : MICROPY_FLOAT_CONST(-1.0); // r[i-1, j]
s = 0.0;
} else if(MICROPY_FLOAT_C_FUN(fabs)(rarray[(i - 1) * n + j]) < LINALG_EPSILON) { // r[i-1, j]
c = 0.0;
s = (rarray[i * n + j] >= 0.0) ? -1.0 : 1.0; // r[i, j]
s = (rarray[i * n + j] >= MICROPY_FLOAT_CONST(0.0)) ? MICROPY_FLOAT_CONST(-1.0) : MICROPY_FLOAT_CONST(1.0); // r[i, j]
} else {
mp_float_t t, u;
if(MICROPY_FLOAT_C_FUN(fabs)(rarray[(i - 1) * n + j]) > MICROPY_FLOAT_C_FUN(fabs)(rarray[i * n + j])) { // r[i-1, j], r[i, j]
t = rarray[i * n + j] / rarray[(i - 1) * n + j]; // r[i, j]/r[i-1, j]
u = MICROPY_FLOAT_C_FUN(sqrt)(1 + t * t);
c = -1.0 / u;
c = MICROPY_FLOAT_CONST(-1.0) / u;
s = c * t;
} else {
t = rarray[(i - 1) * n + j] / rarray[i * n + j]; // r[i-1, j]/r[i, j]
u = MICROPY_FLOAT_C_FUN(sqrt)(1 + t * t);
s = -1.0 / u;
s = MICROPY_FLOAT_CONST(-1.0) / u;
c = s * t;
}
}

View file

@ -29,7 +29,6 @@ author = 'Zoltán Vörös'
# The full version, including alpha/beta/rc tags
release = '5.0.0'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be

View file

@ -1027,10 +1027,17 @@ https://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html
The function reads data from a text file, and returns the generated
array. It takes a file name as the single positional argument, and the
``comments`` (with a default value of ``#``), the ``delimiter`` (with a
default value of ``,``), ``usecols`` (with a default of all columns),
and ``max_rows`` (with a default of all rows) keyword arguments. The
array returned is always of type ``float``.
following keyword arguments:
1. ``comments='#'``
2. ``dtype=float``
3. ``delimiter=','``
4. ``max_rows`` (with a default of all rows)
5. ``skip_rows=0``
6. ``usecols`` (with a default of all columns)
If ``dtype`` is supplied and is not ``float``, the data entries will be
converted to the appropriate integer type by rounding the values.
.. code::
@ -1040,8 +1047,15 @@ array returned is always of type ``float``.
print('read all data')
print(np.loadtxt('loadtxt.dat'))
print('\nread maximum 5 rows (first row is a comment line)')
print(np.loadtxt('loadtxt.dat', max_rows=5))
print('\nread maximum 5 rows, convert dtype (first row is a comment line)')
print(np.loadtxt('loadtxt.dat', max_rows=5, dtype=np.uint8))
print('\nskip the first 3 rows, convert dtype (first row is a comment line)')
print(np.loadtxt('loadtxt.dat', skiprows=3, dtype=np.uint8))
.. parsed-literal::
@ -1052,7 +1066,9 @@ array returned is always of type ``float``.
[12.0, 13.0, 14.0, 15.0],
[16.0, 17.0, 18.0, 19.0],
[20.0, 21.0, 22.0, 23.0],
[24.0, 25.0, 26.0, 27.0]], dtype=float64)
[24.0, 25.0, 26.0, 27.0],
[28.00000000000001, 29.0, 30.0, 31.0],
[32.0, 33.0, 34.00000000000001, 35.0]], dtype=float64)
read maximum 5 rows (first row is a comment line)
array([[0.0, 1.0, 2.0, 3.0],
@ -1060,6 +1076,21 @@ array returned is always of type ``float``.
[8.0, 9.0, 10.0, 11.0],
[12.0, 13.0, 14.0, 15.0]], dtype=float64)
read maximum 5 rows, convert dtype (first row is a comment line)
array([[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11],
[12, 13, 14, 15]], dtype=uint8)
skip the first 3 rows, convert dtype (first row is a comment line)
array([[8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31],
[32, 33, 34, 35]], dtype=uint8)

View file

@ -34,8 +34,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-28T18:34:31.017702Z",
"start_time": "2022-01-28T18:34:31.010354Z"
"end_time": "2022-02-01T17:37:25.505687Z",
"start_time": "2022-02-01T17:37:25.493850Z"
}
},
"outputs": [],
@ -52,8 +52,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-28T18:34:31.565147Z",
"start_time": "2022-01-28T18:34:31.550395Z"
"end_time": "2022-02-01T17:37:25.717714Z",
"start_time": "2022-02-01T17:37:25.532299Z"
}
},
"outputs": [],
@ -1474,16 +1474,25 @@
"\n",
"`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html\n",
"\n",
"The function reads data from a text file, and returns the generated array. It takes a file name as the single positional argument, and the `comments` (with a default value of `#`), the `delimiter` (with a default value of `,`), `usecols` (with a default of all columns), and `max_rows` (with a default of all rows) keyword arguments. The array returned is always of type `float`."
"The function reads data from a text file, and returns the generated array. It takes a file name as the single positional argument, and the following keyword arguments:\n",
"\n",
"1. `comments='#'`\n",
"1. `dtype=float`\n",
"1. `delimiter=','`\n",
"1. `max_rows` (with a default of all rows) \n",
"1. `skip_rows=0`\n",
"1. `usecols` (with a default of all columns)\n",
"\n",
"If `dtype` is supplied and is not `float`, the data entries will be converted to the appropriate integer type by rounding the values."
]
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-28T18:47:52.346814Z",
"start_time": "2022-01-28T18:47:52.291552Z"
"end_time": "2022-02-01T17:41:22.384706Z",
"start_time": "2022-02-01T17:41:22.362821Z"
}
},
"outputs": [
@ -1498,7 +1507,9 @@
" [12.0, 13.0, 14.0, 15.0],\n",
" [16.0, 17.0, 18.0, 19.0],\n",
" [20.0, 21.0, 22.0, 23.0],\n",
" [24.0, 25.0, 26.0, 27.0]], dtype=float64)\n",
" [24.0, 25.0, 26.0, 27.0],\n",
" [28.00000000000001, 29.0, 30.0, 31.0],\n",
" [32.0, 33.0, 34.00000000000001, 35.0]], dtype=float64)\n",
"\n",
"read maximum 5 rows (first row is a comment line)\n",
"array([[0.0, 1.0, 2.0, 3.0],\n",
@ -1506,6 +1517,21 @@
" [8.0, 9.0, 10.0, 11.0],\n",
" [12.0, 13.0, 14.0, 15.0]], dtype=float64)\n",
"\n",
"read maximum 5 rows, convert dtype (first row is a comment line)\n",
"array([[0, 1, 2, 3],\n",
" [4, 5, 6, 7],\n",
" [8, 9, 10, 11],\n",
" [12, 13, 14, 15]], dtype=uint8)\n",
"\n",
"skip the first 3 rows, convert dtype (first row is a comment line)\n",
"array([[8, 9, 10, 11],\n",
" [12, 13, 14, 15],\n",
" [16, 17, 18, 19],\n",
" [20, 21, 22, 23],\n",
" [24, 25, 26, 27],\n",
" [28, 29, 30, 31],\n",
" [32, 33, 34, 35]], dtype=uint8)\n",
"\n",
"\n"
]
}
@ -1517,8 +1543,15 @@
"\n",
"print('read all data')\n",
"print(np.loadtxt('loadtxt.dat'))\n",
"\n",
"print('\\nread maximum 5 rows (first row is a comment line)')\n",
"print(np.loadtxt('loadtxt.dat', max_rows=5))"
"print(np.loadtxt('loadtxt.dat', max_rows=5))\n",
"\n",
"print('\\nread maximum 5 rows, convert dtype (first row is a comment line)')\n",
"print(np.loadtxt('loadtxt.dat', max_rows=5, dtype=np.uint8))\n",
"\n",
"print('\\nskip the first 3 rows, convert dtype (first row is a comment line)')\n",
"print(np.loadtxt('loadtxt.dat', skiprows=3, dtype=np.uint8))"
]
},
{

View file

@ -1,9 +1,21 @@
Sat, 29 Jan 2022
Tue, 1 Feb 2022
version 5.0.0
move scipy.signal.spectrogram to utils.spectrogram
Tue, 1 Feb 2022
version 4.4.2
add skiprows keyword to loadtxt
Sat, 29 Jan 2022
version 4.4.1
add dtype keyword to loadtxt
Thu, 27 Jan 2022
version 4.4.0

View file

@ -17,8 +17,8 @@
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-29T20:50:57.025406Z",
"start_time": "2022-01-29T20:50:56.997334Z"
"end_time": "2022-02-01T17:41:38.040350Z",
"start_time": "2022-02-01T17:41:38.023988Z"
}
},
"outputs": [
@ -218,8 +218,8 @@
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-29T20:51:05.307568Z",
"start_time": "2022-01-29T20:51:04.819263Z"
"end_time": "2022-02-01T17:41:42.215395Z",
"start_time": "2022-02-01T17:41:40.650763Z"
}
},
"outputs": [],
@ -256,7 +256,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-29T20:52:14.453177Z",

View file

@ -3,23 +3,35 @@ try:
except:
import numpy as np
dtypes = (np.uint8, np.int8, np.uint16, np.int16)
a = np.array(range(8)).reshape((2, 4))
np.savetxt('loadtxt.dat', a, header='test file data')
print(np.loadtxt('loadtxt.dat'))
print()
for dtype in dtypes:
print(np.loadtxt('loadtxt.dat', dtype=dtype))
print()
np.savetxt('loadtxt.dat', a, delimiter=',', header='test file data')
print(np.loadtxt('loadtxt.dat', delimiter=','))
print()
np.savetxt('loadtxt.dat', a, delimiter=',', comments='!', header='test file data')
print(np.loadtxt('loadtxt.dat', delimiter=',', comments='!'))
print()
print(np.loadtxt('loadtxt.dat', delimiter=',', comments='!', usecols=1))
print()
print(np.loadtxt('loadtxt.dat', delimiter=',', comments='!', usecols=(0, 1)))
print()
a = np.array(range(36)).reshape((9, 4))
np.savetxt('loadtxt.dat', a, header='9 data rows and a comment')
print(np.loadtxt('loadtxt.dat', max_rows=5))
print()
print(np.loadtxt('loadtxt.dat', skiprows=5, dtype=np.uint16))

View file

@ -1,14 +1,37 @@
array([[0.0, 1.0, 2.0, 3.0],
[4.0, 5.0, 6.0, 7.0]], dtype=float64)
array([[0, 1, 2, 3],
[4, 5, 6, 7]], dtype=uint8)
array([[0, 1, 2, 3],
[4, 5, 6, 7]], dtype=int8)
array([[0, 1, 2, 3],
[4, 5, 6, 7]], dtype=uint16)
array([[0, 1, 2, 3],
[4, 5, 6, 7]], dtype=int16)
array([[0.0, 1.0, 2.0, 3.0],
[4.0, 5.0, 6.0, 7.0]], dtype=float64)
array([[0.0, 1.0, 2.0, 3.0],
[4.0, 5.0, 6.0, 7.0]], dtype=float64)
array([[1.0],
[5.0]], dtype=float64)
array([[0.0, 1.0],
[4.0, 5.0]], dtype=float64)
array([[0.0, 1.0, 2.0, 3.0],
[4.0, 5.0, 6.0, 7.0],
[8.0, 9.0, 10.0, 11.0],
[12.0, 13.0, 14.0, 15.0]], dtype=float64)
array([[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31],
[32, 33, 34, 35]], dtype=uint16)

View file

@ -20,7 +20,7 @@ savetxt with delimiter
6.000000000000000,7.000000000000000,8.000000000000000
savetxt with header
#column1 column2 column3
# column1 column2 column3
0.000000000000000 1.000000000000000 2.000000000000000
3.000000000000000 4.000000000000000 5.000000000000000
6.000000000000000 7.000000000000000 8.000000000000000
@ -29,5 +29,5 @@ savetxt with footer
0.000000000000000 1.000000000000000 2.000000000000000
3.000000000000000 4.000000000000000 5.000000000000000
6.000000000000000 7.000000000000000 8.000000000000000
#written data file
# written data file