198template<
typename T>
void npy_save(std::string fname,
const T* data,
199 const std::vector<size_t> shape, std::string mode =
"w")
207 fp = fopen(fname.c_str(),
"r+b");
215 std::string number_type;
216 parse_npy_header(fp, word_size, true_data_shape, fortran_order, number_type);
217 assert(!fortran_order);
219 if (word_size !=
sizeof(
T))
221 std::cout <<
"libnpy error: " << fname <<
" has word size " << word_size <<
222 " but npy_save appending data sized " <<
sizeof(
T) <<
"\n";
223 assert( word_size ==
sizeof(
T) );
226 if (true_data_shape.size() != shape.size())
229 "libnpy error: npy_save attempting to append misdimensioned data to " << fname
231 assert(true_data_shape.size() != shape.size());
234 for (
size_t i = 1;
i < shape.size();
i++)
236 if (shape[
i] != true_data_shape[
i])
238 std::cout <<
"libnpy error: npy_save attempting to append misshaped data to " <<
240 assert(shape[
i] == true_data_shape[
i]);
244 true_data_shape[0] += shape[0];
248 fp = fopen(fname.c_str(),
"wb");
249 true_data_shape = shape;
253 size_t nels = std::accumulate(shape.begin(), shape.end(), 1,
254 std::multiplies<size_t>());
255 fseek(fp, 0, SEEK_SET);
256 fwrite(&header[0],
sizeof(
char), header.size(), fp);
257 fseek(fp, 0, SEEK_END);
258 fwrite(data,
sizeof(
T), nels, fp);
262template<
typename T>
void npz_save(std::string zipname, std::string fname,
263 const T* data,
const std::vector<size_t>& shape, std::string mode =
"w")
270 size_t global_header_offset = 0;
271 std::vector<char> global_header;
275 fp = fopen(zipname.c_str(),
"r+b");
284 size_t global_header_size;
286 fseek(fp, global_header_offset, SEEK_SET);
287 global_header.resize(global_header_size);
288 size_t res = fread(&global_header[0],
sizeof(
char), global_header_size, fp);
290 if (res != global_header_size)
292 throw std::runtime_error(
"npz_save: header read error while adding to existing zip");
295 fseek(fp, global_header_offset, SEEK_SET);
299 fp = fopen(zipname.c_str(),
"wb");
303 size_t nels = std::accumulate(shape.begin(), shape.end(), 1,
304 std::multiplies<size_t>());
305 size_t nbytes = nels *
sizeof(
T) + npy_header.size();
307 uint32_t crc = crc32(0L, (uint8_t*)&npy_header[0], npy_header.size());
308 crc = crc32(crc, (uint8_t*)data, nels *
sizeof(
T));
310 std::vector<char> local_header;
311 local_header +=
"PK";
312 local_header += (uint16_t) 0x0403;
313 local_header += (uint16_t) 20;
314 local_header += (uint16_t) 0;
315 local_header += (uint16_t) 0;
316 local_header += (uint16_t) 0;
317 local_header += (uint16_t) 0;
318 local_header += (uint32_t) crc;
319 local_header += (uint32_t) nbytes;
320 local_header += (uint32_t) nbytes;
321 local_header += (uint16_t) fname.size();
322 local_header += (uint16_t) 0;
323 local_header += fname;
325 global_header +=
"PK";
326 global_header += (uint16_t) 0x0201;
327 global_header += (uint16_t) 20;
328 global_header.insert(global_header.end(), local_header.begin() + 4,
329 local_header.begin() + 30);
330 global_header += (uint16_t) 0;
331 global_header += (uint16_t) 0;
332 global_header += (uint16_t) 0;
333 global_header += (uint32_t) 0;
334 global_header += (uint32_t)
335 global_header_offset;
336 global_header += fname;
338 std::vector<char> footer;
340 footer += (uint16_t) 0x0605;
341 footer += (uint16_t) 0;
342 footer += (uint16_t) 0;
343 footer += (uint16_t) (nrecs + 1);
344 footer += (uint16_t) (nrecs + 1);
345 footer += (uint32_t) global_header.size();
346 footer += (uint32_t) (global_header_offset + nbytes +
347 local_header.size());
348 footer += (uint16_t) 0;
350 fwrite(&local_header[0],
sizeof(
char), local_header.size(), fp);
351 fwrite(&npy_header[0],
sizeof(
char), npy_header.size(), fp);
352 fwrite(data,
sizeof(
T), nels, fp);
353 fwrite(&global_header[0],
sizeof(
char), global_header.size(), fp);
354 fwrite(&footer[0],
sizeof(
char), footer.size(), fp);
375 const std::vector<size_t>& shape)
377 std::vector<char> dict;
378 dict +=
"{'descr': '";
381 dict += std::to_string(
sizeof(
T));
382 dict +=
"', 'fortran_order': False, 'shape': (";
383 dict += std::to_string(shape[0]);
385 for (
size_t i = 1;
i < shape.size();
i++)
388 dict += std::to_string(shape[
i]);
391 if (shape.size() == 1)
398 int remainder = 16 - (10 + dict.size()) % 16;
399 dict.insert(dict.end(), remainder,
' ');
401 std::vector<char> header;
402 header += (char) 0x93;
404 header += (char) 0x01;
405 header += (char) 0x00;
406 header += (uint16_t) dict.size();
407 header.insert(header.end(), dict.begin(), dict.end());