@@ -314,7 +314,7 @@ function delete(mtVar)
314314 end
315315 end
316316
317- %% Overloaded subsref, subsasg and end
317+ %% Overloaded subsref, subsasgn and end
318318 function [varargout ] = subsref(mtVar , subs )
319319 % - More than one return argument means cell or dot referencing was
320320 % used
@@ -351,67 +351,70 @@ function delete(mtVar)
351351 nNumTotalDims = numel(mtVar .vnDimensionOrder );
352352 vnReferencedTensorSize = size(mtVar );
353353
354- % - Handle different numbers of referencing dimensions
355- if (nNumDims == 1 )
356- % - Translate from linear refs to indices
357- nNumDims = nNumTotalDims ;
358-
359- % - Translate colon indexing
360- if (iscolon(S.subs{1 }))
361- S.subs{1 } = (1 : numel(mtVar ))' ;
362- end
363-
364- % - Get equivalent subscripted indexes
365- vnTensorSize = size(mtVar );
366- [cIndices{1 : nNumDims }] = ind2sub(vnTensorSize , S.subs{1 });
367-
368- % - Permute indices and convert back to linear indexing
369- vnInvOrder(mtVar .vnDimensionOrder(1 : nNumTotalDims )) = 1 : nNumTotalDims ;
370- vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder );
371-
372- try
373- S.subs{1 } = sub2ind(mtVar .vnOriginalSize , cIndices{vnInvOrder });
374- catch
375- error(' MappedTensor:badsubscript' , ...
354+ % - Catch "read entire stack" condition
355+ if (~all(cellfun(@iscolon , S .subs )))
356+ % - Handle different numbers of referencing dimensions
357+ if (nNumDims == 1 )
358+ % - Translate from linear refs to indices
359+ nNumDims = nNumTotalDims ;
360+
361+ % - Translate colon indexing
362+ if (iscolon(S.subs{1 }))
363+ S.subs{1 } = (1 : numel(mtVar ))' ;
364+ end
365+
366+ % - Get equivalent subscripted indexes
367+ vnTensorSize = size(mtVar );
368+ [cIndices{1 : nNumDims }] = ind2sub(vnTensorSize , S.subs{1 });
369+
370+ % - Permute indices and convert back to linear indexing
371+ vnInvOrder(mtVar .vnDimensionOrder(1 : nNumTotalDims )) = 1 : nNumTotalDims ;
372+ vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder );
373+
374+ try
375+ S.subs{1 } = sub2ind(mtVar .vnOriginalSize , cIndices{vnInvOrder });
376+ catch
377+ error(' MappedTensor:badsubscript' , ...
376378 ' *** MappedTensor: Subscript out of range.' );
379+ end
380+
381+ elseif (nNumDims < nNumTotalDims )
382+ % - Wrap up trailing dimensions, matlab style, using linear indexing
383+ vnReferencedTensorSize(nNumDims ) = prod(vnReferencedTensorSize(nNumDims : end ));
384+ vnReferencedTensorSize = vnReferencedTensorSize(1 : nNumDims );
385+
386+ % - Inverse permute index order
387+ vnInvOrder(mtVar .vnDimensionOrder(1 : nNumDims )) = 1 : nNumDims ;
388+ vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder(vnInvOrder ~= 0 ));
389+ S.subs = S .subs(vnInvOrder(vnInvOrder ~= 0 ));
390+
391+ elseif (nNumDims == nNumTotalDims )
392+ % - Simply permute and access tensor
393+
394+ % - Permute index order
395+ vnInvOrder(mtVar .vnDimensionOrder(1 : nNumTotalDims )) = 1 : nNumTotalDims ;
396+ vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder );
397+ S.subs = S .subs(vnInvOrder );
398+
399+ else % (nNumDims > nNumTotalDims)
400+ % - Check for non-colon references
401+ vbNonColon = ~cellfun(@iscolon , S .subs );
402+
403+ % - Check only trailing dimensions
404+ vbNonColon(1 : nNumTotalDims ) = false ;
405+
406+ % - Check trailing dimensions for non-'1' indices
407+ if (any(cellfun(@(c )(~isequal(c , 1 )), S .subs(vbNonColon ))))
408+ % - This is an error
409+ error(' MappedTensor:badsubscript' , ...
410+ ' *** MappedTensor: Subscript out of range.' );
411+ end
412+
413+ % - Permute index order
414+ vnInvOrder(mtVar .vnDimensionOrder(1 : nNumTotalDims )) = 1 : nNumTotalDims ;
415+ vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder );
416+ S.subs = S .subs(vnInvOrder );
377417 end
378-
379- elseif (nNumDims < nNumTotalDims )
380- % - Wrap up trailing dimensions, matlab style, using linear indexing
381- vnReferencedTensorSize(nNumDims ) = prod(vnReferencedTensorSize(nNumDims : end ));
382- vnReferencedTensorSize = vnReferencedTensorSize(1 : nNumDims );
383-
384- % - Inverse permute index order
385- vnInvOrder(mtVar .vnDimensionOrder(1 : nNumDims )) = 1 : nNumDims ;
386- vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder(vnInvOrder ~= 0 ));
387- S.subs = S .subs(vnInvOrder(vnInvOrder ~= 0 ));
388-
389- elseif (nNumDims == nNumTotalDims )
390- % - Simply permute and access tensor
391-
392- % - Permute index order
393- vnInvOrder(mtVar .vnDimensionOrder(1 : nNumTotalDims )) = 1 : nNumTotalDims ;
394- vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder );
395- S.subs = S .subs(vnInvOrder );
396-
397- else % (nNumDims > nNumTotalDims)
398- % - Check for non-colon references
399- vbNonColon = ~cellfun(@iscolon , S .subs );
400-
401- % - Check only trailing dimensions
402- vbNonColon(1 : nNumTotalDims ) = false ;
403-
404- % - Check trailing dimensions for non-'1' indices
405- if (any(cellfun(@(c )(~isequal(c , 1 )), S .subs(vbNonColon ))))
406- % - This is an error
407- error(' MappedTensor:badsubscript' , ...
408- ' *** MappedTensor: Subscript out of range.' );
409- end
410-
411- % - Permute index order
412- vnInvOrder(mtVar .vnDimensionOrder(1 : nNumTotalDims )) = 1 : nNumTotalDims ;
413- vnReferencedTensorSize = vnReferencedTensorSize(vnInvOrder );
414- S.subs = S .subs(vnInvOrder );
415418 end
416419
417420 % - Reference the tensor data element
@@ -876,7 +879,7 @@ function disp(mtVar)
876879 % - Which dimension should we go along?
877880 if (nargin < 3 )
878881 % - Find the first non-singleton dimension
879- [nul , nDim ] = find(vnSize > 1 , 1 , ' first' );
882+ [nul , nDim ] = find(vnSize > 1 , 1 , ' first' ); % #ok<ASGLU>
880883 else
881884 nDim = varargin{2 };
882885 end
@@ -905,7 +908,7 @@ function disp(mtVar)
905908 % - Which dimension should we go along?
906909 if (nargin < 3 )
907910 % - Find the first non-singleton dimension
908- [nul , nDim ] = find(vnSize > 1 , 1 , ' first' );
911+ [nul , nDim ] = find(vnSize > 1 , 1 , ' first' ); % #ok<ASGLU>
909912 else
910913 nDim = varargin{2 };
911914 end
@@ -921,11 +924,11 @@ function disp(mtVar)
921924 end
922925
923926 %% SliceFunction - METHOD Execute a function on the entire tensor, in slices
924- function [mtNewVar ] = SliceFunction(mtVar , fhFunction , nSliceDim , vnSliceSize , varargin )
927+ function [mtNewVar ] = SliceFunction(mtVar , fhFunction , nSliceDim , vnSliceSize , bWriteOnly , varargin )
925928 % SliceFunction - METHOD Execute a function on the entire tensor, in slices
926929 %
927930 % Usage: [<mtNewVar>] = SliceFunction(mtVar,
928- % fhFunctionHandle, nSliceDim <, vnSliceSize,> ...)
931+ % fhFunctionHandle, nSliceDim <, vnSliceSize, bWriteOnly, > ...)
929932 %
930933 % 'mtVar' is a MappedTensor. This tensor will be sliced up along
931934 % dimensions 'nSliceDim', with each slice passed individually to
@@ -1011,6 +1014,14 @@ function disp(mtVar)
10111014 end
10121015 end
10131016
1017+ % - Do we need to read from the source tensor, or does the slice
1018+ % function only write?
1019+ if (nargin(fhFunction ) == 0 ) || exist(' bWriteOnly' , ' var' ) || (bWriteOnly == true )
1020+ bWriteOnly = true ;
1021+ else
1022+ bWriteOnly = false ;
1023+ end
1024+
10141025 % - If an explicit return argument is requested, construct a new tensor
10151026 if (nargout == 1 )
10161027 bNewTensor = true ;
@@ -1075,8 +1086,14 @@ function disp(mtVar)
10751086 mnTheseDestChunks = bsxfun(@plus , mnDestChunkIndices , [(nIndex - 1 ) * nDestWindowStep 0 0 ]);
10761087
10771088 % - Handle a "slice assign" function with no input arguments efficiently
1078- if (nargin(fhFunction ) == 0 )
1079- tData = fhFunction();
1089+ if (bWriteOnly )
1090+ % - Call function
1091+ if (nargin(fhFunction ) == 0 )
1092+ tData = fhFunction();
1093+ else
1094+ tData = fhFunction([], nIndex , varargin{: });
1095+ end
1096+
10801097 mtVar .hShimFunc(' write_chunks' , mtNewVar .hRealContent , mnTheseDestChunks , 1 : numel(tData ), size(tData ), mtNewVar .strClass , mtNewVar .nHeaderBytes , tData ./ mtVar .fRealFactor , mtVar .bBigEndian );
10811098
10821099 else
@@ -1539,31 +1556,62 @@ function isvalidsubscript(oRefs)
15391556
15401557% mt_read_data - FUNCTION Read a set of indices from the file, in an optimsed fashion
15411558function [tData ] = mt_read_data(hShimFunc , hDataFile , sSubs , vnTensorSize , strClass , nHeaderBytes , bBigEndian , hRepSumFunc , hChunkLengthFunc )
1559+
1560+ % - Catch "read whole tensor" condition
1561+ if (all(cellfun(@iscolon , sSubs .subs )))
1562+ nNumStackElems = prod(vnTensorSize );
1563+ vnFileChunkIndices = [1 1 nNumStackElems ];
1564+ tData = 1 : nNumStackElems ; % Use a pre-allocated vector to save memory
1565+
1566+ % - Read data
1567+ tData = hShimFunc(' read_chunks' , hDataFile , vnFileChunkIndices , ...
1568+ tData , tData , vnTensorSize , ...
1569+ strClass , nHeaderBytes , double(bBigEndian ));
1570+
1571+ % - Reshape stack and return
1572+ tData = reshape(tData , vnTensorSize );
1573+ return ;
1574+ end
1575+
15421576 % - Check referencing and convert to linear indices
15431577 [vnLinearIndices , vnDataSize ] = ConvertColonsCheckLims(sSubs .subs , vnTensorSize , hRepSumFunc );
15441578
15451579 % - Maximise chunk probability and minimise number of reads by reading
15461580 % only sorted unique entries
1547- [vnUniqueIndices , nul , vnReverseSort ] = unique_accel(vnLinearIndices );
1581+ [vnLinearIndices , nul , vnReverseSort ] = unique_accel(vnLinearIndices ); % #ok<ASGLU>
15481582
15491583 % - Split into readable chunks
1550- mnFileChunkIndices = SplitFileChunks(vnUniqueIndices , hChunkLengthFunc );
1584+ mnFileChunkIndices = SplitFileChunks(vnLinearIndices , hChunkLengthFunc );
15511585
15521586 % - Call shim read function
1553- tData = hShimFunc(' read_chunks' , hDataFile , mnFileChunkIndices , vnUniqueIndices , vnReverseSort , vnDataSize , strClass , nHeaderBytes , double(bBigEndian ));
1587+ tData = hShimFunc(' read_chunks' , hDataFile , mnFileChunkIndices , vnLinearIndices , vnReverseSort , vnDataSize , strClass , nHeaderBytes , double(bBigEndian ));
15541588end
15551589
15561590% mt_write_data - FUNCTION Read a set of indices from the file, in an optimsed fashion
15571591function mt_write_data(hShimFunc , hDataFile , sSubs , vnTensorSize , strClass , nHeaderBytes , tData , bBigEndian , hRepSumFunc , hChunkLengthFunc )
1592+
1593+ % - Catch "read whole tensor" condition
1594+ if (all(cellfun(@iscolon , sSubs .subs )))
1595+ nNumStackElems = prod(vnTensorSize );
1596+ vnFileChunkIndices = [1 1 nNumStackElems ];
1597+ vnLinearIndices = 1 : nNumStackElems ;
1598+
1599+ % - Write data and return
1600+ hShimFunc(' write_chunks' , hDataFile , vnFileChunkIndices , ...
1601+ vnLinearIndices , vnTensorSize , ...
1602+ strClass , nHeaderBytes , cast(tData , strClass ), double(bBigEndian ));
1603+ return ;
1604+ end
1605+
15581606 % - Check referencing and convert to linear indices
15591607 [vnLinearIndices , vnDataSize ] = ConvertColonsCheckLims(sSubs .subs , vnTensorSize , hRepSumFunc );
15601608
15611609 % - Maximise chunk probability and minimise number of writes by writing
15621610 % only sorted unique entries
1563- [vnUniqueIndices , vnUniqueDataIndices ] = unique_accel(vnLinearIndices );
1611+ [vnLinearIndices , vnUniqueDataIndices ] = unique_accel(vnLinearIndices );
15641612
15651613 % - Split into readable chunks
1566- mnFileChunkIndices = SplitFileChunks(vnUniqueIndices , hChunkLengthFunc );
1614+ mnFileChunkIndices = SplitFileChunks(vnLinearIndices , hChunkLengthFunc );
15671615
15681616 % - Call shim writing function
15691617 hShimFunc(' write_chunks' , hDataFile , mnFileChunkIndices , vnUniqueDataIndices , vnDataSize , strClass , nHeaderBytes , cast(tData , strClass ), double(bBigEndian ));
@@ -1790,7 +1838,7 @@ function mt_write_data_chunks(hDataFile, mnFileChunkIndices, vnUniqueDataIndices
17901838 case ' open'
17911839 if (nargin == 2 )
17921840 [varargout{1 }] = fopen(varargin{1 }, ' r+' );
1793- [nul , nul , varargout{2 }, nul ] = fopen(varargout{1 }); % #ok<NASGU>
1841+ [nul , nul , varargout{2 }, nul ] = fopen(varargout{1 }); % #ok<ASGLU, NASGU>
17941842 else
17951843 varargout{1 } = fopen(varargin{1 }, ' r+' , varargin{2 });
17961844 end
0 commit comments