Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
sub2ind ind2sub substruct

Subject: sub2ind ind2sub substruct

From: Malcolm Lidierth

Date: 30 Sep, 2010 12:46:20

Message: 1 of 6

MATLAB provides an easy way to convert between subscripts and linear indices with sub2ind and ind2sub.
substruct structures in subsref/subsasgn methods do not appear to have any complimentary functions. Below is some code that generates subscripts from a substruct structure. I have two questions:
[1] The code will be called often. Can anyone see a way to speed it up?
[2] For linear index output from
                   subs=struct2sub(siz, index);
                   ind=sub2ind(siz, subs{:});
I want to test whether ind is monotonically increasing or decreasing. At present with
                   if numel(unique(diff(ind)))==1...
Can anyone suggest a test that does not involve generating the indices?

Code:

function subs=struct2sub(siz, index)
% struct2sub returns the subscripts from a substruct structure as a cell array
%
% Example:
% For a matrix M, struct2sub returns the subscripts
% subs=struct2sub(siz, index);
% where siz=size(M) and index is a substruct object (as used by
% subsref or subsasgn methods)
% M may be a field in a structure or object. In that case,
% siz=size(s.fieldname) or size(obj.fieldname)
%
% Generate linear indices from the result using the standard MATLAB sub2ind
% function:
% subs=struct2sub(siz, index);
% ind=sub2ind(siz, subs{:});
       
index=index(end);
n=numel(index.subs);
for k=1:n
    % Deal with non-numeric subscripts
    if ischar(index.subs{k})
        % ':' is the only possibility - I think.
        index.subs{k}=1:siz(k);
    end
end
% Deal with the highest dimension first
subs=cell(1,n);
subs{n}=ndgrid(index.subs{n:-1:1});
subs{n}=reshape(subs{n}, 1, numel(subs{n}));
% Now deal with the rest
for k=n-1:-1:1
    subs{k}=repmat(index.subs{k}, numel(subs{n})/numel(index.subs{k}), 1);
    subs{k}=subs{k}(:).';
end
return
end

Subject: sub2ind ind2sub substruct

From: Jos (10584)

Date: 30 Sep, 2010 13:51:18

Message: 2 of 6

"Malcolm Lidierth" <ku.ca.lck@htreidil.mloclam> wrote in message <i820qs$1h8$1@fred.mathworks.com>...
* snip *
> I want to test whether ind is monotonically increasing or decreasing. At present with
> if numel(unique(diff(ind)))==1...

The call to unique might make it quite slow:

if all(diff(X,2)==0) ...
should do the same

Also note that in a monotonically increasing series the subsequent values of X need not to be separated by the same amount ...

hth
Jos

Subject: sub2ind ind2sub substruct

From: Matt J

Date: 30 Sep, 2010 14:12:04

Message: 3 of 6

"Malcolm Lidierth" <ku.ca.lck@htreidil.mloclam> wrote in message <i820qs$1h8$1@fred.mathworks.com>...

>
> index=index(end);
> n=numel(index.subs);
> for k=1:n
> % Deal with non-numeric subscripts
> if ischar(index.subs{k})
> % ':' is the only possibility - I think.
> index.subs{k}=1:siz(k);
> end
> end
=============

The code confuses me. Does index.sub contain linear index data or subscripts? If the latter, it looks like you could just do

subs=index.subs; return

after replacing the ':' indices with numeric entries. The above code segment looks like it's meant to do that.

If on the other hand, index.subs could also be a linear index the above does not look appropriate. For example, if the substruct is generated by M(:), wouldn't you want

index.subs{k}=1:prod(siz); %for k=1

Subject: sub2ind ind2sub substruct

From: Malcolm Lidierth

Date: 30 Sep, 2010 14:47:21

Message: 4 of 6

Jos
Many thanks. You are right - I did not mean monotonic, rather constant slope

Matt
Index.subs does contain subscripts (as returned by substruct) not linear indices. For my specific application m(:) syntax is dealt with earlier in the subsref method as a special case but I should have generalized this code. If that sounds odd, it might help if I explain that the class I am writing is called "fibber"
% Fibber objects deceive MATLAB: they pretend to be standard MATLAB
% numerical, logical or character variables but really contain a
% memmapfile object that maps data from a file into MATLAB through the
% OSs virtual memory.

Regards
ML

Subject: sub2ind ind2sub substruct

From: Steven_Lord

Date: 30 Sep, 2010 17:52:24

Message: 5 of 6



"Malcolm Lidierth" <ku.ca.lck@htreidil.mloclam> wrote in message
news:i827tp$ke4$1@fred.mathworks.com...
> Jos
> Many thanks. You are right - I did not mean monotonic, rather constant
> slope
>
> Matt
> Index.subs does contain subscripts (as returned by substruct) not linear
> indices. For my specific application m(:) syntax is dealt with earlier in
> the subsref method as a special case but I should have generalized this
> code. If that sounds odd, it might help if I explain that the class I am
> writing is called "fibber"
> % Fibber objects deceive MATLAB: they pretend to be standard MATLAB
> % numerical, logical or character variables but really contain a
> % memmapfile object that maps data from a file into MATLAB through the
> % OSs virtual memory.

Just out of curiosity, how is this different from the regular memmapfile
object included with MATLAB? What functionality does memmapfile not
provide/provide differently than you want that you're trying to add/modify
with your "fibber" class?

--
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
To contact Technical Support use the Contact Us link on
http://www.mathworks.com

Subject: sub2ind ind2sub substruct

From: Malcolm Lidierth

Date: 1 Oct, 2010 10:30:41

Message: 6 of 6

There are several

[1] The fibber subsref does byte swapping if that is needed
[2] It casts the data on disc to the required type
In these respects I have just added features that would be available using fopen/fread on the data
[3] The fibber class includes a Func property that allows a user specified transformation to be applied whenever the data are accessed via subsref. If I want to work e.g. on absolute values I just set Func=@abs and don’t need to edit any of my code.

[3] above works because fibber provides support for obj() syntax. This is redundant for memmapfile because arrays of memmapfiles are not supported. Passing a memmapfile to an existing function expecting a double on input means passing the data in e.g. using filtfilt in the Signal Processing Toolbox
filtfilt(b, a, map.Data);
which rather defeats the point. We’ve passed a variable containing the data in RAM.
With fibber, I would pass the object in:
filtfilt(b, a, obj);
This is where fibbers fibs begin. When filtfilt accesses obj(..) the overloaded subsref interprets that as obj.Map.Data.Adc (…). [Data.Adc is the field with the data in it, so called because fibber generalises the adcarray class which has been on the FEX for some time. That was my first foray into MATLAB OOP and fibber will be a tidier and more general class that will be extended to support adcarrays –see below). None of this gains anything if obj.Map.Data.Adc is a vector, but when it’s a 2-D matrix filtfilt works across the columns and with fibber, only 1 column will be in RAM at any time not the whole matrix. To accomplish this, a few more fibs are needed: As memmapfiles are always 1x1, I can overload size. Then. when filtfilt calls size(obj), fibber returns the value that would be returned by size(obj.Map.Data.Adc). Other methods, such as isreal and isa(obj,
‘double’) also return true as appropriate.

One more trick is needed, and that relates to Matt’s comment above. Much MATLAB code uses x(:) or x(:).’ to get a column or row vector. Following the logic above obj(:) should return a column vector of values from obj.Map.Data.Adc. We make an exception for this case, and simply transpose the dimensions in the Map.Format field if obj contains a vector and that is needed, and pass back the object with the ‘reshaped’ format.

Finally, fibber has convenience constructors. If data are in a –v6 MAT file:
obj=fibber(filename, varname);
or for a structure
obj=fibber(filename, varname, fieldname1,……);
returns the object.

Have a look at sigTOOL to see this working with adcarrays which were designed for handling analog-to-digital converter values. Adcarray subsref calls do the byte swapping, then cast typically int16 values on disc to double, before scaling them and applying a DC offset to return real-world values to the calling m-file.

http://sigtool.sourceforge.net/

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us