Функция работает правильно из MATLAB, но не при вызове из .NET - PullRequest
3 голосов
/ 21 сентября 2011

Я использую MATLAB Builder NE для функциональной совместимости для вызова функций MATLAB из программы на C # .NET, созданной как плагин для приложения с открытым исходным кодом ClearCanvas . Когда я обычно запускаю код из программы .NET, я обычно (но не всегда) получаю сообщение об ошибке

MWMCR :: EvaluateFunction error ... Ссылка на несуществующий элемент массива ячеек. Ошибка в => ComputeT1Maps.m в строке 178.

Строка рассматриваемого кода MATLAB выглядит следующим образом:

seriesHeader = currentSlab.Slice{1}.MetaData{1}.Header;

Заголовок - это структура формы, заданная функцией dicominfo в MATLAB, а MetaData {n} - это структура, которая содержит структуру заголовка имени файла и изображения для n-го файла изображения.

Сигнатура функции для функции ComputeT1Maps:

function ComputeT1Maps(data, options)

Чтобы попытаться выяснить эту ошибку, я поместил следующую строку в начале функции ComputeT1Maps, чтобы сохранить состояние, чтобы я мог видеть, какие значения были переданы в MATLAB из .NET:

save(fullfile('F:\MATLAB\T1Mapping', 'T1_debug.mat'), 'data', 'options', ...
    '-mat', '-v7.3');

Итак, сохранив входные данные для этой функции (полученные из вызывающей ее программы .NET), я попытался запустить функцию ComputeT1Maps из интерактивного сеанса MATLAB после загрузки в сохраненные переменные, чтобы я мог использовать отладку MATLAB. инструменты, чтобы выяснить, почему я получаю ошибку. Вот когда все стало действительно странным. Функция прекрасно работает в интерактивном сеансе MATLAB, когда ей передаются те же самые операнды, которые были ей переданы при вызове из моей программы .NET. Как это может быть? Как может произойти сбой функции при вызове из C # .NET, но она может работать правильно, если в интерактивном сеансе MATLAB вводятся те же данные? Кроме того, этот код раньше работал, и ошибка стала возникать только после того, как я обновил локальную установку MATLAB и MCR до последней версии (2011b).

На стороне .NET data, который передается в MATLAB, создается следующей функцией:

    public void ExchangeData(MultidimensionalDataCollection mdc, string outputPath, bool generateAncillaryTestImages, 
        bool excludeAcquisitions, double[] exclusionList, bool showProgressBar, bool displayComputedImages, 
        bool pauseAtEachSlice, bool softwareDiagnostics, bool displayProgressBar)
    {
        try
        {
            int subspaceIndex = 0;
            int slabIndex = 0;
            int sliceIndex = 0;
            int imageIndex = 0;

            MWStructArray topLevelGrouping;
            MWCellArray geometricSubspaceList;
            MWStructArray geometricGrouping;
            MWCellArray slabList;
            MWStructArray slabGrouping;
            MWCellArray sliceList;
            MWStructArray sliceGrouping;
            MWCellArray imageMetaData;
            MWStructArray perImageData;
            MWArray[] result;
            MWLogicalArray successFlag;
            MWStructArray header;
            MWCellArray sopInstanceUids;
            MWStructArray t1MapOptions;

            topLevelGrouping = new MWStructArray(1, 1, new string[] { "GeometricSubspace", 
                "GeometricSubspaceCount" });
            topLevelGrouping["GeometricSubspaceCount", 1] = mdc.Count;
            geometricSubspaceList = new MWCellArray(1, mdc.Count);

            subspaceIndex = 0;
            foreach (GeometricSubspace subspace in mdc)
            {
                subspaceIndex++;

                geometricGrouping = new MWStructArray(1, 1, new string[] { "Slab", 
                    "SlabCount" });
                geometricGrouping["SlabCount", 1] = subspace.Count;
                slabList = new MWCellArray(1, subspace.Count);

                slabIndex = 0;
                foreach (Slab slab in subspace)
                {
                    slabIndex++;

                    slabGrouping = new MWStructArray(1, 1, new string[] { "Slice", 
                        "SliceCount" });
                    slabGrouping["SliceCount", 1] = slab.Count;
                    sliceList = new MWCellArray(1, slab.Count);

                    sliceIndex = 0;
                    foreach (Slice slice in slab)
                    {
                        sliceIndex++;

                        sliceGrouping = new MWStructArray(1, 1, new string[] { 
                            "ImageCount", "MetaData", "MultidimensionalPixelData",
                            "SliceLocation", "SopInstanceUids" });
                        sliceGrouping["ImageCount", 1] = slice.Count;
                        imageMetaData = new MWCellArray(1, slice.Count);

                        int rows, columns;
                        short[,,,] multidimensionalPixelData = null;

                        imageIndex = 0;
                        foreach (Image image in slice)
                        {
                            imageIndex++;
                            short[,] imageMatrix = null;

                            if (!image.ImageSopClass.DicomUid.Equals(DicomUids.MRImageStorage))
                                throw new NotSupportedException("SopClass " + image.ImageSopClass.Name + " is not supported.");
                            else
                            {
                                DicomUncompressedPixelData rawPixelData = image.PixelData;

                                imageMatrix = GetCCImageMatrix(rawPixelData, out rows, out columns);

                                if (imageIndex == 1)
                                {
                                    multidimensionalPixelData = new short[slice.Count, 1, columns, rows];
                                }

                                for (int i = 0; i < rows; i++)
                                {
                                    for (int j = 0; j < columns; j++)
                                    {
                                        // Remember that C# array indices start with 0 while in MATLAB they start with 1
                                        multidimensionalPixelData[imageIndex - 1, 0, i, j] = imageMatrix[i, j];
                                    }
                                }
                            }
                            perImageData = new MWStructArray(1, 1, new string[] { "FileName", "Header" });
                            perImageData["FileName", 1] = image.FileName;

                            result = _mlT1Mapping.QT1GetDicomHeader(2, image.FileName);

                            if (result == null)
                                throw new Exception("GetDicomHeader failed to read the header file for filename:  " +
                                    image.FileName);
                            else
                            {
                                // MWStructArray
                                successFlag = (MWLogicalArray)result[0];
                                bool[] headerObtained = successFlag.ToVector();
                                if (headerObtained[0])
                                {
                                    header = (MWStructArray)result[1];
                                    perImageData["Header", 1] = header;

                                    imageMetaData[1, imageIndex] = perImageData;
                                }
                                else
                                {
                                    Console.WriteLine("GetDicomHeader failed to read the header file for filename:  " +
                                        image.FileName);
                                }
                            }
                        }
                        sliceList[1, sliceIndex] = sliceGrouping;
                        sliceGrouping["MetaData", 1] = imageMetaData;
                        sliceGrouping["SliceLocation", 1] = slice.SliceLocation;

                        List<string> theSops = slice._sopList;
                        sopInstanceUids = new MWCellArray(1, slice._sopList.Count);

                        int count = 0;
                        foreach (string sop in theSops)
                        {
                            count++;
                            sopInstanceUids[1, count] = sop;
                        }
                        sliceGrouping["SopInstanceUids", 1] = sopInstanceUids;
                        sliceGrouping["MultidimensionalPixelData", 1] = (MWNumericArray)multidimensionalPixelData;
                    }
                    slabList[1, slabIndex] = slabGrouping;
                    slabGrouping["Slice", 1] = sliceList;
                }
                geometricSubspaceList[1, subspaceIndex] = geometricGrouping;
                geometricGrouping["Slab", 1] = slabList;
            }
            topLevelGrouping["GeometricSubspace", 1] = geometricSubspaceList;

            t1MapOptions = new MWStructArray(1, 1, new string[] { "DirectoryPath",
                "ComputeDifferenceImages", "ComputeMultiplicationImages", "DisplayComputedImages", "PauseAtEachSlice",
                "SoftwareDiagnostics", "DisplayProgressBar"
            });

            t1MapOptions["DirectoryPath"] = (MWCharArray)outputPath;
            t1MapOptions["SaveS0Maps"] = (MWLogicalArray)generateAncillaryTestImages;
            t1MapOptions["ExcludeAcquisitions"] = (MWLogicalArray)excludeAcquisitions;
            t1MapOptions["ExclusionList"] = (MWNumericArray)exclusionList;
            t1MapOptions["DisplayComputedImages"] = (MWLogicalArray)displayComputedImages;
            t1MapOptions["PauseAtEachSlice"] = (MWLogicalArray)pauseAtEachSlice;
            t1MapOptions["SoftwareDiagnostics"] = (MWLogicalArray)softwareDiagnostics;
            t1MapOptions["DisplayProgressBar"] = (MWLogicalArray)displayProgressBar;

            _mlT1Mapping.ComputeT1Maps(topLevelGrouping, t1MapOptions);
        }
        catch (Exception)
        {
            throw;
        }
    }

1 Ответ

1 голос
/ 26 сентября 2011

Я еще не уверен на 100%, что все исправил, но пока что после нескольких изменений тесты кажутся успешными.Похоже, суть проблемы заключалась в том, что порядок некоторых назначений был транспонирован.Это произошло в нескольких местах.Например, вместо:

sliceList[1, sliceIndex] = sliceGrouping;
sliceGrouping["MetaData", 1] = imageMetaData;

его следовало бы упорядочить следующим образом:

sliceGrouping["MetaData", 1] = imageMetaData;
sliceList[1, sliceIndex] = sliceGrouping;

Странная вещь в этой ошибке заключалась в том, что код отлично работал в предыдущей версии MATLAB,Он никогда не должен был работать вообще!

...