Размер структуры внутри другой структуры в Matlab (R2010a 64-разрядная версия Linux)

Я работаю с Matlab API, который загружает данные из проприетарного формата в ряд структур. Вот пример того, как выглядит набор данных после загрузки файла:

>> (имена полей данных (1))

ANS =

'Grid_Point_ID'
'Grid_Point_Latitude'
'Grid_Point_Longitude'
'Grid_Point_Altitude'
'Grid_Point_Mask'
'BT_Data'

>> данные (1).BT_Data

ANS =

BT_Data: [1x66 struct]

>> имена полей (data(1).BT_Data(1))

ANS =

'Flags'
'BT_Value_Real'
'BT_Value_Imag'
'Pixel_Radiometric_Accuracy'
'Incidence_Angle'
'Azimuth_Angle'
'Faraday_Rotation_Angle'
'Geometric_Rotation_Angle'
'Snapshot_ID_of_Pixel'
'Footprint_Axis1'
'Footprint_Axis2'

Я хочу перебрать все data(i).BT_Data(j), У меня уже есть длина data хорошо, но я не могу получить размер / длину BT_Data (который варьируется для каждого data(i)):

>> длина (данные (1).BT_Data)

ANS =

 1

>> размер (данные (1).BT_Data)

ANS =

 1     1

Мой ожидаемый результат здесь ans = 66 (или эквивалентный массив для size()).

Я не очень знаком с форматом данных структуры, который может быть частью моей борьбы. Но length(data) работал нормально, поэтому я запутался, почему он не будет работать на BT_Data (Я тоже пробовал BT_Data(:)).

Самый релевантный предыдущий ответ, который я могу найти, это 1757250, но я не смог заставить его работать (я думаю, что он здесь не применим). Спасибо за любую информацию, которую вы можете предоставить.

------ РЕДАКТИРОВАТЬ ------

Вот немного больше понимания того, как я должен использовать API, чтобы даже добраться до точки, где я нахожусь:

>> system ('ln -sf /opt/rwapi-matlab/lib/rwapi/smos/config/xml_rw_api.usr_conf.xml.');
SetEnv('XML_RW_API_HOME','/ Opt / rwapi-Matlab / Библиотека /rwapi');
Путь (путь, '/ Opt / rwapi-MATLAB');

>> prod = RWAPI.product ('SM_OPEB_MIR_SCLF1C_20110202T013659_20110202T014642_346_060_1')

Массив SMOS Matlab Interface версия 1.4
(c) 2010 Array Systems Computing Inc. из Канады ( http://www.array.ca/)
Распространение или модификация этого программного обеспечения требует письменного разрешения от Array

продукт =

RWAPI.product handle
Package: RWAPI

Properties:
     filename: 'SM_OPEB_MIR_SCLF1C_20110202T013659_20110202T014642_346_060_1'
       header: [1x1 struct]
xml_datablock: []

Методы, события, суперклассы

>> data = prod.dataset(2)

данные =

Дескриптор RWAPI.dataset без свойств. Пакет: RWAPI

Методы, события, суперклассы

>> данные (1)

ANS =

       Grid_Point_ID: 251721
 Grid_Point_Latitude: 25.5000
Grid_Point_Longitude: -102.2590
 Grid_Point_Altitude: 1.4714e+03
     Grid_Point_Mask: 2
             BT_Data: [1x66 struct]

>> данные (1).BT_Data

ANS =

BT_Data: [1x66 struct]

>> данные (1).BT_Data (1)

ANS =

                     Flags: 6229
             BT_Value_Real: 262.5275
             BT_Value_Imag: 0
Pixel_Radiometric_Accuracy: 6160
           Incidence_Angle: 31966
             Azimuth_Angle: 10299
    Faraday_Rotation_Angle: 65277
  Geometric_Rotation_Angle: 58605
      Snapshot_ID_of_Pixel: 65752530
           Footprint_Axis1: 19649
           Footprint_Axis2: 14625

>> чьи
Имя Размер Байты Атрибуты класса

ANS 1x1 1 логический
данные 1x19091 112 RWAPI.dataset
продукт 1x2 112 RWAPI.product

3 ответа

Решение

Хорошо, я действительно подозреваю, что это странность в переопределенном методе subsref в этих классах RWAPI. Я смог воспроизвести все ваше наблюдаемое поведение, определив класс со слегка патологическим подрефом.

classdef stupidref
    %STUPIDREF Reproduce odd indexing behavior that jpatton saw. Buggy.
    properties
        BT_Data = repmat(struct('foo',42, 'bar',42), [1 66]);
    end
    methods
        function B = subsref(A,S)
            s = S(1);
            subs = s.subs;
            chain = S(2:end);

            switch s.type
                case '()'
                    B = builtin( 'subsref', A, s );
                    if ~isempty(chain)
                        B = subsref(B, chain);
                    end

                case '.'
                    % Non-standard behavior!
                    if ~isempty(chain) && isequal(chain(1).type, '()')
                        B = subsref(A.(s.subs), chain);
                    else
                        B = struct(s.subs, A.(s.subs));
                    end
            end
        end
    end
end

Это соответствует странной разнице между data(1).BT_Data а также fieldnames(data(1).BT_Data(1))и завершение табуляции, которое многократно добавляет ".BT_Data".

>> data = stupidref;
>> data(1).BT_Data
ans = 
    BT_Data: [1x66 struct]
>> fieldnames(data(1).BT_Data)
ans = 
    'BT_Data'
>> fieldnames(data(1).BT_Data(1))
ans = 
    'foo'
    'bar'
>> length(data(1).BT_Data)
ans =
     1
>> data(1).BT_Data.BT_Data.BT_Data.BT_Data.BT_Data.BT_Data % produced by tab-completion
ans = 
    BT_Data: [1x66 struct]
>> 

Ваш обходной путь хорош - как только вы позвоните a = data(1).BT_Data, у вас есть нормальная структура, и нестандартный подреф уже не существует. Вы можете получить тот же эффект в одной строке с getfield,

>> btdata = getfield(data(1).BT_Data, 'BT_Data')
btdata = 
1x66 struct array with fields:
    foo
    bar

Я бы сообщил об этом как о возможной ошибке авторам библиотеки RWAPI.

Не стесняйтесь просто отредактировать этот код в своем собственном обходном ответе; это не столько ответ, сколько поддержка диагностики.

Я нашел обходной путь, хотя он не очень удовлетворяет:

>> a = data (1).BT_Data

а =

BT_Data: [1x66 struct]

>> длина (a.BT_Data)

ANS =

66

Я отмечу это как ответ на данный момент, потому что я сомневаюсь, что будет какой-то другой "правильный" способ сделать это.

Эндрю ответил на вопрос (и почему этот обходной путь работает).

Некоторые из ваших результатов кажутся противоречивыми. Для начала, если поле BT_Data содержал структурный массив размером 1 на 66, я бы ожидал, что результат будет выглядеть так:

>> data(1).BT_Data

ans =

1x66 struct array with fields:
     Flags
     ...    %# etc.

Тот факт, что вы видите это:

>> data(1).BT_Data

ans =

BT_Data: [1x66 struct]

подсказывает мне, что BT_Data на самом деле структура 1 на 1 с одним полем под названием BT_Dataи это поле содержит структурный массив размером 1 на 66. Это объясняет, что вы видите, когда вы получаете длину и размер первого BT_Data (структура 1 на 1). Если это так, вы должны получить следующие результаты:

>> size(data(1).BT_Data.BT_Data)

ans =

     1     66

Однако это все еще не объясняет вывод, который вы видите, когда делаете:

fieldnames(data(1).BT_Data(1))

Это сбивает меня с толку. Вы можете проверить это BT_Data на самом деле это структура, а не какой-то другой тип объекта, который может иметь другое поведение индексации и отображения, выполняя это:

isstruct(data(1).BT_Data)

И это должно вернуть 1 если BT_Data это структура.

Другие вопросы по тегам