Question

I'm using MATLAB Builder NE for interoperability to call MATLAB functions from a C# .NET program built as a plug-in for the open source application ClearCanvas. When I run the code normally from the .NET program, I usually (but not always) get the error message

MWMCR::EvaluateFunction error ... Reference to non-existent element of a cell array. Error in => ComputeT1Maps.m at line 178.

The line of MATLAB code in question is as follows:

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

Header is a struct of the form given by MATLAB's dicominfo function and MetaData{n} is a struct that contains the filename and image header struct for the nth image file.

The function signature for the ComputeT1Maps function is:

function ComputeT1Maps(data, options)

To try to figure out this bug I put the following line in at the beginning of the ComputeT1Maps function in order to preserve state so I could see what values were passed to MATLAB from .NET:

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

So, having preserved the inputs to this function (received from the .NET program that called it), I then tried running my ComputeT1Maps function from an interactive MATLAB session after loading in the saved variables, so that I could utilize MATLAB's debugging tools to figure out why I was getting the error. That's when things got really bizarre. The function works just fine from the interactive MATLAB session when given the exact same operands that were given to it when it was called from my .NET program. How can this be? How can the function fail when called from C# .NET, but run properly when given the exact same input in an interactive MATLAB session? Also, this same code used to work before and the error only began to happen after I updated both my local installation of MATLAB and the MCR to the latest version (2011b).

On the .NET side, the data that is passed to MATLAB is constructed by the following function:

    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;
        }
    }
Was it helpful?

Solution

I'm not yet 100% certain that I've fixed everything, but so far the tests appear to be succeeding after a few changes. It seems that the crux of the problem was that the order of some assignments was transposed. This occurred in a few places. For example, instead of:

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

it should have been ordered as:

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

The strange thing about this bug was that the code worked just fine in the previous version of MATLAB. It should have never worked at all!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top