loadbinary.m 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. function m = loadbinary(file,precision,msize,lastdimrange,dim)
  2. % function m = loadbinary(file,precision,msize,lastdimrange,dim)
  3. %
  4. % <file> is a pattern matching one or more files (see matchfiles.m)
  5. % <precision> is something like 'int16'
  6. % <msize> (optional) is the expected dimensions of the matrix for one file.
  7. % one of the dimensions can be 0, in which case we figure out what
  8. % that number should be. default: [1 0].
  9. % <lastdimrange> (optional) is
  10. % [A B] where A<=B and A and B are indices referring to the last dimension
  11. % of <m> (i.e. the last entry in <msize>). this indicates that we
  12. % want the portion of the matrix that lies between A to B (inclusive.)
  13. % -V where V is a vector of indices referring to the last dimension of <m>.
  14. % this indicates that we want exactly the indices specified by V. V can
  15. % have indices in any order and may include repeats.
  16. % we read and return only the portion of the matrix specified by
  17. % <lastdimrange>. default is [], which means return the whole matrix.
  18. % <dim> (optional) is the dimension along which to concatenate
  19. % matrices from different files. default: 1.
  20. %
  21. % read <file> and return a matrix. we assume that each file contains
  22. % some data (i.e. it isn't empty). for the machine format, we assume
  23. % IEEE floating point with little-endian byte ordering ('l'; see fopen).
  24. %
  25. % see also savebinary.m.
  26. %
  27. % example:
  28. % savebinary('test','uint8',repmat(0:255,[2 1]));
  29. % isequal(loadbinary('test','uint8',[0 256],[255 256]),repmat([254 255],[2 1]))
  30. % constants
  31. machineformat = 'l';
  32. % input
  33. if ~exist('msize','var') || isempty(msize)
  34. msize = [1 0];
  35. end
  36. if ~exist('lastdimrange','var') || isempty(lastdimrange)
  37. lastdimrange = [];
  38. end
  39. if ~exist('dim','var') || isempty(dim)
  40. dim = 1;
  41. end
  42. % massage input
  43. if ~isempty(lastdimrange)
  44. if any(lastdimrange < 0)
  45. lastdimrange = -lastdimrange;
  46. else
  47. lastdimrange = lastdimrange(1):lastdimrange(2);
  48. end
  49. end
  50. % get file name
  51. file = matchfiles(file);
  52. assert(length(file) >= 1,'<file> does not match at least one file');
  53. % loop through files
  54. for p=1:length(file)
  55. % open file
  56. fid = fopen(file{p},'r',machineformat);
  57. assert(fid ~= -1,'<file> could not be opened for reading');
  58. % handle case of no specific range
  59. if isempty(lastdimrange)
  60. % read it all in
  61. m0 = fread(fid,Inf,['*' precision],0,machineformat);
  62. % figure out msize
  63. if any(msize==0)
  64. assert(sum(msize==0)==1); % make sure only one is 0
  65. msize(msize==0) = prod(size(m0))/prod(msize(msize~=0)); % calc appropriate value
  66. assert(all(isint(msize)),'<msize> is not correct');
  67. end
  68. % reshape
  69. m0 = reshape(m0,msize);
  70. % handle case of specific range
  71. else
  72. % peek to find out the byte size of a word
  73. temp = fread(fid,1,['*' precision],0,machineformat);
  74. wordsize = getfield(whos('temp'),'bytes');
  75. % check how big the data segment is
  76. assert(fseek(fid,0,'bof')==0);
  77. pos1 = ftell(fid); assert(pos1~=-1);
  78. assert(fseek(fid,0,'eof')==0);
  79. pos2 = ftell(fid); assert(pos2~=-1);
  80. % calculate number of words
  81. numwords = (pos2-pos1)/wordsize; assert(isint(numwords));
  82. % figure out msize
  83. if any(msize==0)
  84. assert(sum(msize==0)==1); % make sure only one is 0
  85. msize(msize==0) = numwords/prod(msize(msize~=0)); % calc appropriate value
  86. assert(all(isint(msize)),'<msize> is not correct');
  87. end
  88. % calc slice size in terms of number of words
  89. slicesize = prod(msize(1:end-1));
  90. % ok, now we have to do fancy handling to deal with arbitrary vectors of indices
  91. % process chunks of consecutive indices
  92. lastdimrange_sorted = sort(lastdimrange);
  93. cur = 1; % pos in sorted list that we are on currently
  94. m0 = cast([],precision); % initialize
  95. while cur <= length(lastdimrange_sorted)
  96. ff = find(diff(lastdimrange_sorted(cur:end))~=1); % ff(1) tells us how many consecutive integers we have
  97. if isempty(ff) % in this case, the entire list is consecutive integers
  98. rng = [lastdimrange_sorted(cur) lastdimrange_sorted(end)];
  99. cur = cur + diff(rng)+1;
  100. else
  101. rng = [lastdimrange_sorted(cur) lastdimrange_sorted(cur)+ff(1)-1];
  102. cur = cur + ff(1);
  103. end
  104. % calc number of slices wanted
  105. numslices = rng(2)-rng(1)+1;
  106. % read data and reshape
  107. assert(fseek(fid,slicesize*(rng(1)-1)*wordsize,'bof')==0);
  108. m0 = cat(length(msize),m0,reshape(fread(fid,numslices*slicesize,['*' precision],0,machineformat),[msize(1:end-1) numslices]));
  109. end
  110. % now, return exactly what the user wanted
  111. m0 = subscript(m0,[repmat({':'},[1 length(msize)-1]) {calcposition(lastdimrange_sorted,lastdimrange)}]);
  112. end
  113. % close file
  114. assert(fclose(fid)==0);
  115. % save
  116. if p==1
  117. m = m0; % get the datatype right instead of initializing to double via []
  118. else
  119. m = cat(dim,m,m0);
  120. end
  121. end