matlab - 从下标参考中查找每个维度中的所有索引位置
问题描述
是否有一种优雅的方式可以在重载时从下标引用中检索所有索引位置(对于每个维度)subsref
。假设例如 array a = rand(3, 5, 4, 2);
,那么下面的下标是等价的:
a() <=> a(:,:,:,:)
a(1, 12) <=> a(1, 2, 3, 1)
a(2, :, 5) <=> a(2, :, 1, 2)
a(2, 3, end:-5:1) <=> a(2, 3, 4, 2), a(2, 3, 3, 1)
a(2, 3, 4, 1, :, 1) <=> a(2, 3, 4, 1)
logic = [false, true, false];
a(logic, 5, 2, 1) <=> a(2, 5, 2, 1)
我感兴趣的是为每个维度找到索引的唯一位置。从上面的例子可以看出:
a() => idx1 = [1,2,3]; idx2 = [1,2,3,4,5]; idx3 = [1,2,3,4]; idx4 = [1,2];
a(1, 12) => idx1 = [1]; idx2 = [2]; idx3 = [3]; idx4 = [1];
a(2, :, 5) => idx1 = [2]; idx2 = [1,2,3,4,5]; idx3 = [1]; idx4 = [2];
a(2, 3, end:-5:1) => idx1 = [2]; idx2 = [3]; idx3 = [3,4]; idx4 = [1,2];
a(2, 3, 4, 1, :, 1) => idx1 = [2]; idx2 = [3]; idx3 = [4]; idx4 = [1];
logic = [false, true, false];
a(logic, 5, 2, 1) => idx1 = [2]; idx2 = [5]; idx3 = [2]; idx4 = [1];
我想这样做的原因有点复杂,但简而言之,我有一个 matlab 类以一种投影模式存储数据,但我仍然希望能够以其他各种投影模式访问数据(主要用于显示目的)。因此,我有依赖属性,可以对存储的数据进行动态转换。
到目前为止,很好,问题是对于从一种投影模式到另一种投影模式的某些数据坐标(累积点)是模棱两可的,除非我知道我在哪个切割(即哪个下标)......能够预先检测一个尺寸在下标之后变为标量 我可以很聪明,并检查是否可以在返回计算值之前对其进行返工...例如,这将避免在一维中绘制数据时出现伪影,因为在一次切割中,您必须选择一个公式并在另一个切另一个。
这是我通过重载subsref
方法和解析下标描述结构提出的解决方案:
classdef TestSubscript < handle
% Lifetime
methods
function [this] = TestSubscript()
n = 3; m = 5; k = 4; l = 2;
this.EAz = rand(n,m,k,l);
this.EEl = rand(n,m,k,l);
end
end
% Really stored values in projection mode 1
properties(Access=private)
EAz;
EEl;
end
% Projection in mode 2 computed on the fly
properties(Dependent)
EPhi;
end
methods
% Generic formula
function [ephi] = get.EPhi(this)
ephi = (sqrt(2)/2)*(this.EAz + this.EEl); % This is dummy (real formula is more complex and depends on coordinates)
end
% Detection of special cuts
function [varargout] = subsref(this, s)
% First call built-in to apply generic formula
[varargout{1:nargout}] = builtin('subsref', this, s);
if ((length(s) ~= 2) || ~strcmp(s(1).type, '.') || ~strcmp(s(1).subs, 'EPhi') || ~strcmp(s(2).type, '()'))
return;
end
% Then find selected positions on each dimension for this.EPhi(....lalala....) before returning value
ndim = ndims(this.EAz);
selectedPositions = cell(1, ndim);
subscript = s(2).subs;
scount = length(subscript);
if (scount == 0)
% Call like 'r = this.EPhi();'
for ki = 1:ndim,
selectedPositions{ki} = 1:size(this.EAz, ki);
end
else
% Call like 'r = this.EPhi(...lalalala....);'
for ki = 1:ndim,
if (ki < scount)
% Ok subscript really corresponds to current dimension
selectedPositions{ki} = subscript{ki};
if (ischar(selectedPositions{ki}) && strcmp(selectedPositions{ki}, ':'))
selectedPositions{ki} = 1:size(this.EAz, ki);
elseif (islogical(selectedPositions{ki}))
fullidx = 1:size(this.EAz, ki);
selectedPositions{ki} = fullidx(selectedPositions{ki});
end
else
% Subscript is a mix of all remaining dimensions
mix = subscript{ki};
sizmix = size(this.EAz); sizmix = sizmix(ki:ndim);
if (ischar(mix) && strcmp(mix, ':'))
mix = 1:prod(sizmix);
elseif (islogical(mix))
fullidx = 1:prod(sizmix);
mix = fullidx(mix);
end
[selectedPositions{ki:ndim}] = ind2sub(sizmix, mix);
break;
end
end
end
% Make special action if we detect we are on a special cut
allAzAxisIndexedPositions = unique(selectedPositions{1});
allElAxisIdxexedPositions = unique(selectedPositions{2});
if ((length(allAzAxisIndexedPositions) == 1) && (length(allElAxisIdxexedPositions) > 1))
% We are on vertical cut, TODO: check Az = 0° and force phi = 0° for all encountered accumulation points (Az = 0°, El = 0°)
disp('Vertical cut detected ... should use formula one');
elseif ((length(allAzAxisIndexedPositions) > 1) && (length(allElAxisIdxexedPositions) == 1))
% We are on horizontal cut, TODO: check El = 0° and force phi = 90° for all encountered acummulation points (Az = 0°, El = 0°)
disp('Horizontal cut detected ... should use formula two');
else
% Nothing we can do
disp('Nothing special ... can only use generic formula');
end
end
end
end
然后我可以检测切割(注意:只有前两个轴对公式选择很重要):
a = TestSubscript;
a.EPhi(:, :, 3, 1);
Nothing special ... can only use generic formula
a.EPhi(1, :, 3, 1);
Vertical cut detected ... should use formula one
a.EPhi(:, 2, 3, 1);
Horizontal cut detected ... should use formula two
与“在每个维度上查找选定位置”相关的代码块已经很短了,但也许有更简单的解决方案可以找到所有索引位置?
解决方案
推荐阅读
- typeorm - TypeORM:useContainer 是做什么的?
- c# - 使用 DataAnnotations 进行模型验证 [DataType(DataType.Currency]
- r - 将数据集中的变量传递给调用 dplyr 的函数
- regex - 如何在正则表达式中以非固定宽度向后看
- java - Scanner accepts wrong input
- python - 移动矩形冻结到最终状态,而不是执行每个移动
- python - 使用 Python3,是否有一种简单的方法来过滤数据帧 [WaypointID1, WaypointID2] 以仅将起始 waypointIDs 转换为最终 waypointIDs
- java - Android 上 org.springframework.web.util.UriComponentsBuilder.newInstance 的 ExceptionInInitializerError
- html - 如何使这两个图像的大小与其包含的 div 相同?
- c - 如何计算输入的数字?