Merge pull request #471 from v923z/io

implement numpy.save, numpy.load
This commit is contained in:
Zoltán Vörös 2022-01-19 19:57:38 +01:00 committed by GitHub
commit 16b277fe1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 629 additions and 37 deletions

View file

@ -19,6 +19,7 @@ SRC_USERMOD += $(USERMODULES_DIR)/numpy/create.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/fft/fft.c SRC_USERMOD += $(USERMODULES_DIR)/numpy/fft/fft.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/fft/fft_tools.c SRC_USERMOD += $(USERMODULES_DIR)/numpy/fft/fft_tools.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/filter.c SRC_USERMOD += $(USERMODULES_DIR)/numpy/filter.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/io/io.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg.c SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg_tools.c SRC_USERMOD += $(USERMODULES_DIR)/numpy/linalg/linalg_tools.c
SRC_USERMOD += $(USERMODULES_DIR)/numpy/numerical.c SRC_USERMOD += $(USERMODULES_DIR)/numpy/numerical.c

375
code/numpy/io/io.c Normal file
View file

@ -0,0 +1,375 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Zoltán Vörös
*/
#include <string.h>
#include <stdio.h>
#include "py/builtin.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "../../ndarray.h"
#include "io.h"
#define ULAB_IO_BUFFER_SIZE 128
#define ULAB_IO_NULL_ENDIAN 0
#define ULAB_IO_LITTLE_ENDIAN 1
#define ULAB_IO_BIG_ENDIAN 2
#if ULAB_NUMPY_HAS_LOAD
static void io_read_(mp_obj_t stream, const mp_stream_p_t *stream_p, char *buffer, char *string, uint16_t len, int *error) {
size_t read = stream_p->read(stream, buffer, len, error);
bool fail = false;
if(read == len) {
if(string != NULL) {
if(memcmp(buffer, string, len) != 0) {
fail = true;
}
}
} else {
fail = true;
}
if(fail) {
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, error);
mp_raise_msg(&mp_type_RuntimeError, translate("corrupted file"));
}
}
static mp_obj_t io_load(mp_obj_t file) {
if(!mp_obj_is_str(file)) {
mp_raise_TypeError(translate("wrong input type"));
}
int error;
char *buffer = m_new(char, ULAB_IO_BUFFER_SIZE);
// test for endianness
uint16_t x = 1;
int8_t native_endianness = (x >> 8) == 1 ? ULAB_IO_BIG_ENDIAN : ULAB_IO_LITTLE_ENDIAN;
mp_obj_t open_args[2] = {
file,
MP_OBJ_NEW_QSTR(MP_QSTR_rb)
};
mp_obj_t stream = mp_builtin_open(2, open_args, (mp_map_t *)&mp_const_empty_map);
const mp_stream_p_t *stream_p = mp_get_stream(stream);
// read header
// magic string
io_read_(stream, stream_p, buffer, "\x93NUMPY", 6, &error);
// simply discard the version number
io_read_(stream, stream_p, buffer, NULL, 2, &error);
// header length, represented as a little endian uint16 (0x76, 0x00)
io_read_(stream, stream_p, buffer, NULL, 2, &error);
uint16_t header_length = buffer[1];
header_length <<= 8;
header_length += buffer[0];
// beginning of the dictionary describing the array
io_read_(stream, stream_p, buffer, "{'descr': '", 11, &error);
uint8_t dtype;
io_read_(stream, stream_p, buffer, NULL, 1, &error);
uint8_t endianness = ULAB_IO_NULL_ENDIAN;
if(*buffer == '<') {
endianness = ULAB_IO_LITTLE_ENDIAN;
} else if(*buffer == '>') {
endianness = ULAB_IO_BIG_ENDIAN;
}
io_read_(stream, stream_p, buffer, NULL, 2, &error);
if(memcmp(buffer, "u1", 2) == 0) {
dtype = NDARRAY_UINT8;
} else if(memcmp(buffer, "i1", 2) == 0) {
dtype = NDARRAY_INT8;
} else if(memcmp(buffer, "u2", 2) == 0) {
dtype = NDARRAY_UINT16;
} else if(memcmp(buffer, "i2", 2) == 0) {
dtype = NDARRAY_INT16;
}
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
else if(memcmp(buffer, "f4", 2) == 0) {
dtype = NDARRAY_FLOAT;
}
#else
else if(memcmp(buffer, "f8", 2) == 0) {
dtype = NDARRAY_FLOAT;
}
#endif
#if ULAB_SUPPORTS_COMPLEX
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
else if(memcmp(buffer, "c8", 2) == 0) {
dtype = NDARRAY_COMPLEX;
}
#else
else if(memcmp(buffer, "c16", 3) == 0) {
dtype = NDARRAY_COMPLEX;
}
#endif
#endif /* ULAB_SUPPORT_COPMLEX */
else {
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
mp_raise_TypeError(translate("wrong dtype"));
}
io_read_(stream, stream_p, buffer, "', 'fortran_order': False, 'shape': (", 37, &error);
size_t *shape = m_new(size_t, ULAB_MAX_DIMS);
memset(shape, 0, sizeof(size_t) * ULAB_MAX_DIMS);
uint16_t bytes_to_read = MIN(ULAB_IO_BUFFER_SIZE, header_length - 51);
// bytes_to_read is 128 at most. This should be enough to contain a
// maximum of 4 size_t numbers plus the delimiters
io_read_(stream, stream_p, buffer, NULL, bytes_to_read, &error);
char *needle = buffer;
uint8_t ndim = 0;
// find out the number of dimensions by counting the commas in the string
while(1) {
if(*needle == ',') {
ndim++;
if(needle[1] == ')') {
break;
}
} else if((*needle == ')') && (ndim > 0)) {
ndim++;
break;
}
needle++;
}
needle = buffer;
for(uint8_t i = 0; i < ndim; i++) {
size_t number = 0;
// trivial number parsing here
while(1) {
if((*needle == ' ') || (*needle == '\t')) {
needle++;
}
if((*needle > 47) && (*needle < 58)) {
number = number * 10 + (*needle - 48);
} else if((*needle == ',') || (*needle == ')')) {
break;
}
else {
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
mp_raise_msg(&mp_type_RuntimeError, translate("corrupted file"));
}
needle++;
}
needle++;
shape[ULAB_MAX_DIMS - ndim + i] = number;
}
// strip the rest of the header
if((bytes_to_read + 51) < header_length) {
io_read_(stream, stream_p, buffer, NULL, header_length - (bytes_to_read + 51), &error);
}
ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(ndim, shape, dtype);
char *array = (char *)ndarray->array;
size_t read = stream_p->read(stream, array, ndarray->len * ndarray->itemsize, &error);
if(read != ndarray->len * ndarray->itemsize) {
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
mp_raise_msg(&mp_type_RuntimeError, translate("corrupted file"));
}
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
m_del(char, buffer, ULAB_IO_BUFFER_SIZE);
// swap the bytes, if necessary
if((native_endianness != endianness) && (dtype != NDARRAY_UINT8) && (dtype != NDARRAY_INT8)) {
uint8_t sz = ndarray->itemsize;
char *tmpbuff = NULL;
#if ULAB_SUPPORTS_COMPLEX
if(dtype == NDARRAY_COMPLEX) {
// work with the floating point real and imaginary parts
sz /= 2;
tmpbuff = m_new(char, sz);
for(size_t i = 0; i < ndarray->len; i++) {
for(uint8_t k = 0; k < 2; k++) {
tmpbuff += sz;
for(uint8_t j = 0; j < sz; j++) {
memcpy(--tmpbuff, array++, 1);
}
memcpy(array-sz, tmpbuff, sz);
}
}
} else {
#endif
tmpbuff = m_new(char, sz);
for(size_t i = 0; i < ndarray->len; i++) {
tmpbuff += sz;
for(uint8_t j = 0; j < sz; j++) {
memcpy(--tmpbuff, array++, 1);
}
memcpy(array-sz, tmpbuff, sz);
}
#if ULAB_SUPPORTS_COMPLEX
}
#endif
m_del(char, tmpbuff, sz);
}
return MP_OBJ_FROM_PTR(ndarray);
}
MP_DEFINE_CONST_FUN_OBJ_1(io_load_obj, io_load);
#endif /* ULAB_NUMPY_HAS_LOAD */
#if ULAB_NUMPY_HAS_SAVE
static mp_obj_t io_save(mp_obj_t file, mp_obj_t ndarray_) {
if(!mp_obj_is_str(file) || !mp_obj_is_type(ndarray_, &ulab_ndarray_type)) {
mp_raise_TypeError(translate("wrong input type"));
}
ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(ndarray_);
int error;
char *buffer = m_new(char, ULAB_IO_BUFFER_SIZE);
uint8_t offset = 0;
// test for endianness
uint16_t x = 1;
int8_t native_endiannes = (x >> 8) == 1 ? '>' : '<';
mp_obj_t open_args[2] = {
file,
MP_OBJ_NEW_QSTR(MP_QSTR_wb)
};
mp_obj_t stream = mp_builtin_open(2, open_args, (mp_map_t *)&mp_const_empty_map);
const mp_stream_p_t *stream_p = mp_get_stream(stream);
// write header;
// magic string + header length, which is always 128 - 10 = 118, represented as a little endian uint16 (0x76, 0x00)
// + beginning of the dictionary describing the array
memcpy(buffer, "\x93NUMPY\x01\x00\x76\x00{'descr': '", 21);
offset += 21;
buffer[offset] = native_endiannes;
if((ndarray->dtype == NDARRAY_UINT8) || (ndarray->dtype == NDARRAY_INT8)) {
// for single-byte data, the endianness doesn't matter
buffer[offset] = '|';
}
offset++;
switch(ndarray->dtype) {
case NDARRAY_UINT8:
memcpy(buffer+offset, "u1", 2);
break;
case NDARRAY_INT8:
memcpy(buffer+offset, "i1", 2);
break;
case NDARRAY_UINT16:
memcpy(buffer+offset, "u2", 2);
break;
case NDARRAY_INT16:
memcpy(buffer+offset, "i2", 2);
break;
case NDARRAY_FLOAT:
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
memcpy(buffer+offset, "f4", 2);
#else
memcpy(buffer+offset, "f8", 2);
#endif
break;
#if ULAB_SUPPORTS_COMPLEX
case NDARRAY_COMPLEX:
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
memcpy(buffer+offset, "c8", 2);
#else
memcpy(buffer+offset, "c16", 3);
offset++;
#endif
break;
#endif
}
offset += 2;
memcpy(buffer+offset, "', 'fortran_order': False, 'shape': (", 37);
offset += 37;
if(ndarray->ndim == 1) {
offset += sprintf(buffer+offset, "%zu,", ndarray->shape[ULAB_MAX_DIMS - 1]);
} else {
for(uint8_t i = ndarray->ndim; i > 1; i--) {
offset += sprintf(buffer+offset, "%zu, ", ndarray->shape[ULAB_MAX_DIMS - i]);
}
offset += sprintf(buffer+offset, "%zu", ndarray->shape[ULAB_MAX_DIMS - 1]);
}
memcpy(buffer+offset, "), }", 4);
offset += 4;
// pad with space till the very end
memset(buffer+offset, 32, ULAB_IO_BUFFER_SIZE - offset - 1);
buffer[ULAB_IO_BUFFER_SIZE - 1] = '\n';
stream_p->write(stream, buffer, ULAB_IO_BUFFER_SIZE, &error);
// write the array data
uint8_t sz = ndarray->itemsize;
offset = 0;
uint8_t *array = (uint8_t *)ndarray->array;
#if ULAB_MAX_DIMS > 3
size_t i = 0;
do {
#endif
#if ULAB_MAX_DIMS > 2
size_t j = 0;
do {
#endif
#if ULAB_MAX_DIMS > 1
size_t k = 0;
do {
#endif
size_t l = 0;
do {
memcpy(buffer+offset, array, sz);
offset += sz;
if(offset == ULAB_IO_BUFFER_SIZE) {
stream_p->write(stream, buffer, offset, &error);
offset = 0;
}
array += ndarray->strides[ULAB_MAX_DIMS - 1];
l++;
} while(l < ndarray->shape[ULAB_MAX_DIMS - 1]);
#if ULAB_MAX_DIMS > 1
array -= ndarray->strides[ULAB_MAX_DIMS - 1] * ndarray->shape[ULAB_MAX_DIMS-1];
array += ndarray->strides[ULAB_MAX_DIMS - 2];
k++;
} while(k < ndarray->shape[ULAB_MAX_DIMS - 2]);
#endif
#if ULAB_MAX_DIMS > 2
array -= ndarray->strides[ULAB_MAX_DIMS - 2] * ndarray->shape[ULAB_MAX_DIMS-2];
array += ndarray->strides[ULAB_MAX_DIMS - 3];
j++;
} while(j < ndarray->shape[ULAB_MAX_DIMS - 3]);
#endif
#if ULAB_MAX_DIMS > 3
array -= ndarray->strides[ULAB_MAX_DIMS - 3] * ndarray->shape[ULAB_MAX_DIMS-3];
array += ndarray->strides[ULAB_MAX_DIMS - 4];
i++;
} while(i < ndarray->shape[ULAB_MAX_DIMS - 4]);
#endif
stream_p->write(stream, buffer, offset, &error);
stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error);
m_del(char, buffer, ULAB_IO_BUFFER_SIZE);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(io_save_obj, io_save);
#endif /* ULAB_NUMPY_HAS_SAVE */

17
code/numpy/io/io.h Normal file
View file

@ -0,0 +1,17 @@
/*
* This file is part of the micropython-ulab project,
*
* https://github.com/v923z/micropython-ulab
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Zoltán Vörös
*/
#ifndef _ULAB_IO_
#define _ULAB_IO_
MP_DECLARE_CONST_FUN_OBJ_2(io_save_obj);
MP_DECLARE_CONST_FUN_OBJ_1(io_load_obj);
#endif

View file

@ -23,6 +23,7 @@
#include "create.h" #include "create.h"
#include "fft/fft.h" #include "fft/fft.h"
#include "filter.h" #include "filter.h"
#include "io/io.h"
#include "linalg/linalg.h" #include "linalg/linalg.h"
#include "numerical.h" #include "numerical.h"
#include "stats.h" #include "stats.h"
@ -256,6 +257,9 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
#if ULAB_NUMPY_HAS_FLIP #if ULAB_NUMPY_HAS_FLIP
{ MP_OBJ_NEW_QSTR(MP_QSTR_flip), (mp_obj_t)&numerical_flip_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_flip), (mp_obj_t)&numerical_flip_obj },
#endif #endif
#if ULAB_NUMPY_HAS_LOAD
{ MP_OBJ_NEW_QSTR(MP_QSTR_load), (mp_obj_t)&io_load_obj },
#endif
#if ULAB_NUMPY_HAS_MINMAX #if ULAB_NUMPY_HAS_MINMAX
{ MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&numerical_max_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&numerical_max_obj },
#endif #endif
@ -271,6 +275,9 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = {
#if ULAB_NUMPY_HAS_ROLL #if ULAB_NUMPY_HAS_ROLL
{ MP_OBJ_NEW_QSTR(MP_QSTR_roll), (mp_obj_t)&numerical_roll_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_roll), (mp_obj_t)&numerical_roll_obj },
#endif #endif
#if ULAB_NUMPY_HAS_SAVE
{ MP_OBJ_NEW_QSTR(MP_QSTR_save), (mp_obj_t)&io_save_obj },
#endif
#if ULAB_NUMPY_HAS_SIZE #if ULAB_NUMPY_HAS_SIZE
{ MP_OBJ_NEW_QSTR(MP_QSTR_size), (mp_obj_t)&transform_size_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_size), (mp_obj_t)&transform_size_obj },
#endif #endif

View file

@ -33,7 +33,7 @@
#include "user/user.h" #include "user/user.h"
#include "utils/utils.h" #include "utils/utils.h"
#define ULAB_VERSION 4.2.1 #define ULAB_VERSION 4.3.0
#define xstr(s) str(s) #define xstr(s) str(s)
#define str(s) #s #define str(s) #s

View file

@ -462,6 +462,10 @@
#define ULAB_NUMPY_HAS_INTERP (1) #define ULAB_NUMPY_HAS_INTERP (1)
#endif #endif
#ifndef ULAB_NUMPY_HAS_LOAD
#define ULAB_NUMPY_HAS_LOAD (1)
#endif
#ifndef ULAB_NUMPY_HAS_MEAN #ifndef ULAB_NUMPY_HAS_MEAN
#define ULAB_NUMPY_HAS_MEAN (1) #define ULAB_NUMPY_HAS_MEAN (1)
#endif #endif
@ -486,6 +490,10 @@
#define ULAB_NUMPY_HAS_ROLL (1) #define ULAB_NUMPY_HAS_ROLL (1)
#endif #endif
#ifndef ULAB_NUMPY_HAS_SAVE
#define ULAB_NUMPY_HAS_SAVE (1)
#endif
#ifndef ULAB_NUMPY_HAS_SIZE #ifndef ULAB_NUMPY_HAS_SIZE
#define ULAB_NUMPY_HAS_SIZE (1) #define ULAB_NUMPY_HAS_SIZE (1)
#endif #endif

View file

@ -27,7 +27,7 @@ copyright = '2019-2022, Zoltán Vörös and contributors'
author = 'Zoltán Vörös' author = 'Zoltán Vörös'
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = '4.2.0' release = '4.3.0'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------

View file

@ -11,7 +11,7 @@ the firmware was compiled with complex support.
3. `numpy.argmax <#argmax>`__ 3. `numpy.argmax <#argmax>`__
4. `numpy.argmin <#argmin>`__ 4. `numpy.argmin <#argmin>`__
5. `numpy.argsort <#argsort>`__ 5. `numpy.argsort <#argsort>`__
6. `numpy.asarray <#asarray>`__ 6. `numpy.asarray\* <#asarray>`__
7. `numpy.clip <#clip>`__ 7. `numpy.clip <#clip>`__
8. `numpy.compress\* <#compress>`__ 8. `numpy.compress\* <#compress>`__
9. `numpy.conjugate\* <#conjugate>`__ 9. `numpy.conjugate\* <#conjugate>`__
@ -25,25 +25,27 @@ the firmware was compiled with complex support.
17. `numpy.interp <#interp>`__ 17. `numpy.interp <#interp>`__
18. `numpy.isfinite <#isfinite>`__ 18. `numpy.isfinite <#isfinite>`__
19. `numpy.isinf <#isinf>`__ 19. `numpy.isinf <#isinf>`__
20. `numpy.max <#max>`__ 20. `numpy.load <#load>`__
21. `numpy.maximum <#maximum>`__ 21. `numpy.max <#max>`__
22. `numpy.mean <#mean>`__ 22. `numpy.maximum <#maximum>`__
23. `numpy.median <#median>`__ 23. `numpy.mean <#mean>`__
24. `numpy.min <#min>`__ 24. `numpy.median <#median>`__
25. `numpy.minimum <#minimum>`__ 25. `numpy.min <#min>`__
26. `numpy.not_equal <#equal>`__ 26. `numpy.minimum <#minimum>`__
27. `numpy.polyfit <#polyfit>`__ 27. `numpy.not_equal <#equal>`__
28. `numpy.polyval <#polyval>`__ 28. `numpy.polyfit <#polyfit>`__
29. `numpy.real\* <#real>`__ 29. `numpy.polyval <#polyval>`__
30. `numpy.roll <#roll>`__ 30. `numpy.real\* <#real>`__
31. `numpy.size <#size>`__ 31. `numpy.roll <#roll>`__
32. `numpy.sort <#sort>`__ 32. `numpy.save <#save>`__
33. `numpy.sort_complex\* <#sort_complex>`__ 33. `numpy.size <#size>`__
34. `numpy.std <#std>`__ 34. `numpy.sort <#sort>`__
35. `numpy.sum <#sum>`__ 35. `numpy.sort_complex\* <#sort_complex>`__
36. `numpy.trace <#trace>`__ 36. `numpy.std <#std>`__
37. `numpy.trapz <#trapz>`__ 37. `numpy.sum <#sum>`__
38. `numpy.where <#where>`__ 38. `numpy.trace <#trace>`__
39. `numpy.trapz <#trapz>`__
40. `numpy.where <#where>`__
all all
--- ---
@ -982,6 +984,39 @@ positions, where the input is infinite. Integer types return the
load
----
``numpy``:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.load.html
The function reads data from a file in ``numpy``\ s
`platform-independent
format <https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html#module-numpy.lib.format>`__,
and returns the generated array. If the endianness of the data in the
file and the microcontroller differ, the bytes are automatically
swapped.
.. code::
# code to be run in micropython
from ulab import numpy as np
a = np.load('a.npy')
print(a)
.. parsed-literal::
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, 16.0, 17.0, 18.0, 19.0],
[20.0, 21.0, 22.0, 23.0, 24.0]], dtype=float64)
mean mean
---- ----
@ -1430,6 +1465,25 @@ Vertical rolls require two internal copies of single columns.
save
----
``numpy``:
https://docs.scipy.org/doc/numpy/reference/generated/numpy.save.html
With the help of this function, numerical array can be save in
``numpy``\ s `platform-independent
format <https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html#module-numpy.lib.format>`__.
The function takes two positional arguments, the name of the output
file, and the array.
.. code::
# code to be run in CPython
a = np.array(range(25)).reshape((5, 5))
np.save('a.npy', a)
size size
---- ----

View file

@ -34,8 +34,8 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2022-01-14T19:55:15.200755Z", "end_time": "2022-01-15T08:50:03.152522Z",
"start_time": "2022-01-14T19:55:15.193656Z" "start_time": "2022-01-15T08:50:03.141317Z"
} }
}, },
"outputs": [], "outputs": [],
@ -52,8 +52,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2022-01-14T19:55:17.871864Z", "end_time": "2022-01-15T08:50:04.183008Z",
"start_time": "2022-01-14T19:55:17.858935Z" "start_time": "2022-01-15T08:50:04.162758Z"
} }
}, },
"outputs": [], "outputs": [],
@ -237,7 +237,7 @@
"1. [numpy.argmax](#argmax)\n", "1. [numpy.argmax](#argmax)\n",
"1. [numpy.argmin](#argmin)\n", "1. [numpy.argmin](#argmin)\n",
"1. [numpy.argsort](#argsort)\n", "1. [numpy.argsort](#argsort)\n",
"1. [numpy.asarray](#asarray)\n", "1. [numpy.asarray*](#asarray)\n",
"1. [numpy.clip](#clip)\n", "1. [numpy.clip](#clip)\n",
"1. [numpy.compress*](#compress)\n", "1. [numpy.compress*](#compress)\n",
"1. [numpy.conjugate*](#conjugate)\n", "1. [numpy.conjugate*](#conjugate)\n",
@ -251,6 +251,7 @@
"1. [numpy.interp](#interp)\n", "1. [numpy.interp](#interp)\n",
"1. [numpy.isfinite](#isfinite)\n", "1. [numpy.isfinite](#isfinite)\n",
"1. [numpy.isinf](#isinf)\n", "1. [numpy.isinf](#isinf)\n",
"1. [numpy.load](#load)\n",
"1. [numpy.max](#max)\n", "1. [numpy.max](#max)\n",
"1. [numpy.maximum](#maximum)\n", "1. [numpy.maximum](#maximum)\n",
"1. [numpy.mean](#mean)\n", "1. [numpy.mean](#mean)\n",
@ -262,6 +263,7 @@
"1. [numpy.polyval](#polyval)\n", "1. [numpy.polyval](#polyval)\n",
"1. [numpy.real*](#real)\n", "1. [numpy.real*](#real)\n",
"1. [numpy.roll](#roll)\n", "1. [numpy.roll](#roll)\n",
"1. [numpy.save](#save)\n",
"1. [numpy.size](#size)\n", "1. [numpy.size](#size)\n",
"1. [numpy.sort](#sort)\n", "1. [numpy.sort](#sort)\n",
"1. [numpy.sort_complex*](#sort_complex)\n", "1. [numpy.sort_complex*](#sort_complex)\n",
@ -1418,6 +1420,50 @@
"print('\\nisinf(c):\\n', np.isinf(c))" "print('\\nisinf(c):\\n', np.isinf(c))"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## load\n",
"\n",
"`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.load.html\n",
"\n",
"The function reads data from a file in `numpy`'s [platform-independent format](https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html#module-numpy.lib.format), and returns the generated array. If the endianness of the data in the file and the microcontroller differ, the bytes are automatically swapped."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-12T19:11:10.361592Z",
"start_time": "2022-01-12T19:11:10.342439Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"array([[0.0, 1.0, 2.0, 3.0, 4.0],\n",
" [5.0, 6.0, 7.0, 8.0, 9.0],\n",
" [10.0, 11.0, 12.0, 13.0, 14.0],\n",
" [15.0, 16.0, 17.0, 18.0, 19.0],\n",
" [20.0, 21.0, 22.0, 23.0, 24.0]], dtype=float64)\n",
"\n",
"\n"
]
}
],
"source": [
"%%micropython -unix 1\n",
"\n",
"from ulab import numpy as np\n",
"\n",
"a = np.load('a.npy')\n",
"print(a)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
@ -1999,6 +2045,34 @@
"print(\"\\na rolled with None:\\n\", a)" "print(\"\\na rolled with None:\\n\", a)"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## save\n",
"\n",
"`numpy`: https://docs.scipy.org/doc/numpy/reference/generated/numpy.save.html\n",
"\n",
"With the help of this function, numerical array can be save in `numpy`'s [platform-independent format](https://numpy.org/doc/stable/reference/generated/numpy.lib.format.html#module-numpy.lib.format).\n",
"\n",
"The function takes two positional arguments, the name of the output file, and the array. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2022-01-15T08:51:08.827144Z",
"start_time": "2022-01-15T08:51:08.813813Z"
}
},
"outputs": [],
"source": [
"a = np.array(range(25)).reshape((5, 5))\n",
"np.save('a.npy', a)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
@ -2013,8 +2087,8 @@
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2022-01-14T19:58:44.044501Z", "end_time": "2022-01-15T08:50:57.254168Z",
"start_time": "2022-01-14T19:58:44.034585Z" "start_time": "2022-01-15T08:50:57.245772Z"
} }
}, },
"outputs": [ "outputs": [

View file

@ -1,3 +1,9 @@
Wed, 19 Jan 2022
version 4.3.0
implement numpy.save, numpy.load
Tue, 18 Jan 2022 Tue, 18 Jan 2022
version 4.2.1 version 4.2.1
@ -10,6 +16,12 @@ version 4.2.0
add numpy.size, asarray add numpy.size, asarray
Wed, 12 Jan 2022
version 4.2.0
implement numpy.save, numpy.load
Wed, 12 Jan 2022 Wed, 12 Jan 2022
version 4.1.1 version 4.1.1

View file

@ -17,8 +17,8 @@
"execution_count": 1, "execution_count": 1,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2022-01-14T19:54:52.171096Z", "end_time": "2022-01-15T08:48:23.883953Z",
"start_time": "2022-01-14T19:54:52.162815Z" "start_time": "2022-01-15T08:48:23.877040Z"
} }
}, },
"outputs": [ "outputs": [
@ -61,7 +61,7 @@
"author = 'Zoltán Vörös'\n", "author = 'Zoltán Vörös'\n",
"\n", "\n",
"# The full version, including alpha/beta/rc tags\n", "# The full version, including alpha/beta/rc tags\n",
"release = '4.2.0'\n", "release = '4.3.0'\n",
"\n", "\n",
"\n", "\n",
"# -- General configuration ---------------------------------------------------\n", "# -- General configuration ---------------------------------------------------\n",
@ -218,8 +218,8 @@
"execution_count": 2, "execution_count": 2,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2022-01-14T20:05:37.425494Z", "end_time": "2022-01-15T08:48:32.207113Z",
"start_time": "2022-01-14T20:05:35.620545Z" "start_time": "2022-01-15T08:48:32.051714Z"
} }
}, },
"outputs": [], "outputs": [],
@ -256,11 +256,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
"end_time": "2022-01-14T20:06:04.832792Z", "end_time": "2022-01-15T08:52:20.686225Z",
"start_time": "2022-01-14T20:06:00.259738Z" "start_time": "2022-01-15T08:52:16.125014Z"
} }
}, },
"outputs": [], "outputs": [],

View file

@ -0,0 +1,14 @@
try:
from ulab import numpy as np
except:
import numpy as np
dtypes = (np.uint8, np.int8, np.uint16, np.int16, np.float)
for dtype in dtypes:
a = np.array(range(25), dtype=dtype)
b = a.reshape((5, 5))
np.save('out.npy', a)
print(np.load('out.npy'))
np.save('out.npy', b)
print(np.load('out.npy'))

View file

@ -0,0 +1,30 @@
array([0, 1, 2, ..., 22, 23, 24], dtype=uint8)
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]], dtype=uint8)
array([0, 1, 2, ..., 22, 23, 24], dtype=int8)
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]], dtype=int8)
array([0, 1, 2, ..., 22, 23, 24], dtype=uint16)
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]], dtype=uint16)
array([0, 1, 2, ..., 22, 23, 24], dtype=int16)
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]], dtype=int16)
array([0.0, 1.0, 2.0, ..., 22.0, 23.0, 24.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, 16.0, 17.0, 18.0, 19.0],
[20.0, 21.0, 22.0, 23.0, 24.0]], dtype=float64)