constructNPYheader.m 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. % NPY-MATLAB constructNPYheader function. Copied from https://github.com/kwikteam/npy-matlab
  2. function header = constructNPYheader(dataType, shape, varargin)
  3. if ~isempty(varargin)
  4. fortranOrder = varargin{1}; % must be true/false
  5. littleEndian = varargin{2}; % must be true/false
  6. else
  7. fortranOrder = true;
  8. littleEndian = true;
  9. end
  10. dtypesMatlab = {'uint8','uint16','uint32','uint64','int8','int16','int32','int64','single','double', 'logical'};
  11. dtypesNPY = {'u1', 'u2', 'u4', 'u8', 'i1', 'i2', 'i4', 'i8', 'f4', 'f8', 'b1'};
  12. magicString = uint8([147 78 85 77 80 89]); %x93NUMPY
  13. majorVersion = uint8(1);
  14. minorVersion = uint8(0);
  15. % build the dict specifying data type, array order, endianness, and
  16. % shape
  17. dictString = '{''descr'': ''';
  18. if littleEndian
  19. dictString = [dictString '<'];
  20. else
  21. dictString = [dictString '>'];
  22. end
  23. dictString = [dictString dtypesNPY{strcmp(dtypesMatlab,dataType)} ''', '];
  24. dictString = [dictString '''fortran_order'': '];
  25. if fortranOrder
  26. dictString = [dictString 'True, '];
  27. else
  28. dictString = [dictString 'False, '];
  29. end
  30. dictString = [dictString '''shape'': ('];
  31. % if length(shape)==1 && shape==1
  32. %
  33. % else
  34. % for s = 1:length(shape)
  35. % if s==length(shape) && shape(s)==1
  36. %
  37. % else
  38. % dictString = [dictString num2str(shape(s))];
  39. % if length(shape)>1 && s+1==length(shape) && shape(s+1)==1
  40. % dictString = [dictString ','];
  41. % elseif length(shape)>1 && s<length(shape)
  42. % dictString = [dictString ', '];
  43. % end
  44. % end
  45. % end
  46. % if length(shape)==1
  47. % dictString = [dictString ','];
  48. % end
  49. % end
  50. for s = 1:length(shape)
  51. dictString = [dictString num2str(shape(s))];
  52. if s<length(shape)
  53. dictString = [dictString ', '];
  54. end
  55. end
  56. dictString = [dictString '), '];
  57. dictString = [dictString '}'];
  58. totalHeaderLength = length(dictString)+10; % 10 is length of magicString, version, and headerLength
  59. headerLengthPadded = ceil(double(totalHeaderLength+1)/16)*16; % the whole thing should be a multiple of 16
  60. % I add 1 to the length in order to allow for the newline character
  61. % format specification is that headerlen is little endian. I believe it comes out so using this command...
  62. headerLength = typecast(int16(headerLengthPadded-10), 'uint8');
  63. zeroPad = zeros(1,headerLengthPadded-totalHeaderLength, 'uint8')+uint8(32); % +32 so they are spaces
  64. zeroPad(end) = uint8(10); % newline character
  65. header = uint8([magicString majorVersion minorVersion headerLength dictString zeroPad]);
  66. end