I'm having trouble reading a text file in Unity3D.
I've created a method which returns a type float[][] and takes a streamreader as argument:
public float[][] CreateWeights(StreamReader reader){
int n = 0;
float[][] Weights = new float[50][];
while((!reader.EndOfStream)){
string text = reader.ReadLine();
if (text == null)
break;
string[] strFloats = text.Split (new char[0]);
float[] floats = new float[strFloats.Length];
for(int i = 0; i<strFloats.Length; i++){
floats[i] = float.Parse(strFloats[i]);
}
Weights[n] = floats;
n++;
}
return Weights;
}
I make use of this method in void Start() to create "weights":
float[][] WeightsIH;
float[][] WeightsHO;
void Start(){
FileInfo theSourceFile = new FileInfo(Application.dataPath + "/Resources/WeightsIH.txt");
StreamReader reader = theSourceFile.OpenText();
FileInfo theSourceFile2 = new FileInfo(Application.dataPath + "/Resources/WeightsHO.txt");
StreamReader reader2 = theSourceFile2.OpenText();
WeightsIH = CreateWeights(reader);
WeightsHO = CreateWeights(reader2);
Yhidden = new float[50][];
HiddenOutput = new float[50][];
Xoutput = new float[1];
}
And this will work fine in Unity's play mode. However, after creating an executable, the files won't be found, which I do understand. So to make it work, I understood that I need to use Resources.Load and I have:
void Start(){
TextAsset text1 = Resources.Load("WeightsIH") as TextAsset;
TextAsset text2 = Resources.Load("WeightsHO") as TextAsset;
WeightsIH = CreateWeights(text1);
WeightsHO = CreateWeights(text2);
Yhidden = new float[50][];
HiddenOutput = new float[50][];
Xoutput = new float[1];
}
Of course the argument type can't be a streamReader anymore, and I changed it to take TextAsset as argument. Here's how it changed:
public float[][] CreateWeights(TextAsset textAsset){
float[][] Weights = new float[50][];
string[] linesFromFile = textAsset.text.Split("\n"[0]);
for(int i = 0; i<linesFromFile.Length; i++){
string[] strFloats = linesFromFile[i].Split (new char[0]);
float[] floats = new float[strFloats.Length];
for(int j = 0; j<strFloats.Length; j++){
floats[j] = float.Parse(strFloats[j]);
}
Weights[i] = floats;
}
return Weights;
}
Now this won't work at all, not even in play mode. The run-time error I would get is as follows:
FormatException: Invalid format.
System.Double.Parse (System.String s, NumberStyles style,
IFormatProvider provider) ( at
/Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Double.cs:209)
System.Single.Parse (System.String s) ( at
/Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Single.cs:183)
FollowShortestPath.CreateWeights (UnityEngine.TextAsset textAsset)
( at Assets/Scripts/Pathfinding/FollowShortestPath.cs:203)
FollowShortestPath.Start () ( at
Assets/Scripts/Pathfinding/FollowShortestPath.cs:54)
line 54 refers to:
WeightsIH = CreateWeights(text1);
and line 203 refers to:
floats[j] = float.Parse(strFloats[j]);
What am I doing wrong? How can I get the text files to be read successfully in in the executable?
The problem you have is with text file format you are loading.
Couse you have many white spaces
string[] strFloats = text.Split (new char[0]);
will result in that some strings are empty.
To fix this, remove extra withe spaces from text files or use:
for(int j = 0; j<strFloats.Length; j++){
if (string.IsNullOrEmpty (strFloats [j]))
continue;
floats[j] = float.Parse(strFloats[j]);
}
Related
I am new to structs in C# and I am stuck and can not pass the values in a file back to struct and successfully read them again.
The initialisation values work fine, but the file will not load at all
This is what I have so far:
public struct Card
{
public char suit;//'C'- Clubs, 'D'-Diamonds,'H'- Hearts
//and 'S'- Spades
public int value;//2-14 – for 2-10, Jack, Queen, King, Ace
}
static void Main(string[] args)
{
const int CARDS_IN_HAND = 5;//number of cards in hand
Card[] hand = new Card[CARDS_IN_HAND];//array of cards
InitialiseArray(hand);
Console.WriteLine("-------------\n");
Console.WriteLine("Initialised Values in Array");
DisplayHandData(hand);
Console.ReadLine();
The issue seems to be below
LoadArray(hand);//load values into array for use
//check values loaded to array
Console.WriteLine("-------------\n");
Console.WriteLine("Actuals Values in Array from file");
DisplayHandData(hand);
Console.ReadLine();
}
public static void InitialiseArray(Card[] data)
{
for (int count = 0; count < data.Length; count++)
{
data[count].suit = 'C';
data[count].value = 0;
}
}
public static void LoadArray(Card[] data)
{
string fileName = "FullHouse.txt";//name of file for menu item 3
//data in file = C 13 H 13 D 13 C 10 H 10
string input = fileName;
List<Card> cards = new List<Card>();
//string input = fileName;
StreamReader inFile = new StreamReader(fileName);//open file
input = inFile.ReadLine();//priming read for array
string[] inputArray = input.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
//input loading data into array
for (int i = 0; i < 10; i += 2)
{
Card newCard = new Card();
newCard.suit = inputArray[i][0];
newCard.value = int.Parse(inputArray[i + 1]);
cards.Add(newCard);
}
inFile.Close();
}
public static void DisplayHandData(Card[] data)
{
Console.WriteLine();
//test values loaded into array in correct positions
for (int records = 0; records < data.Length; records++)
{
Console.WriteLine(data[records].suit);
Console.WriteLine(data[records].value);
}
Console.WriteLine("-------------\n");
Console.ReadLine();
}
Any help would be greatly appreciated.
Your LoadArray should work just fine. The problem is probably that you are filling in variable cards, which is a local List<Card>, but what you probably want to do is fill in the data parameter.
Here is my sugestion for altering the for-cycle in LoadArray method
for (int i = 0; i < data.Length; ++i)
{
Card newCard = new Card();
newCard.suit = inputArray[i * 2][0];
newCard.value = int.Parse(inputArray[i * 2 + 1]);
data[i] = newCard;
}
But be careful about this approach. It is quite fragile. If there will be a mismatch in the length of data and inputArray, you will get an exception (if inputArray will be shorter than expected). You should check the length before the for-cycle.
Your LoadArray() method isn't changing the contents of the array passed in to it.
I recommend using a List in your main method instead, and change LoadArray() to:
public static List<Card> LoadArray()
{
string fileName = "FullHouse.txt";//name of file for menu item 3
//data in file = C 13 H 13 D 13 C 10 H 10
string input = fileName;
List<Card> cards = new List<Card>();
//string input = fileName;
StreamReader inFile = new StreamReader(fileName);//open file
input = inFile.ReadLine();//priming read for array
string[] inputArray = input.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
//input loading data into array
for (int i = 0; i < 10; i += 2)
{
Card newCard = new Card();
newCard.suit = inputArray[i][0];
newCard.value = int.Parse(inputArray[i + 1]);
cards.Add(newCard);
}
inFile.Close();
return cards;
}
Then you shouldn't need the InitialiseArray() method at all.
Instead you can do:
var hand = LoadArray();
Of course, then you might want to rename LoadArray() to something like LoadHand().
You can check, the value using Console.WriteLine(hand.Count) this will give you the size, and you can display your data in hand some like this
foreach(var h in hand)
{
Console.WriteLine(h.suit);
Console.WriteLine(h.value);
}
if you wish you can try this too.
hand.ForEach(h=>
{
Console.WriteLine(h.suit);
Console.WriteLine(h.value);
});
Edited:
Sorry, Matthew; I should put this as a comment under your answer. :-)
I have static class theat declare the array:
static class GlobalDataClass
{
public static double[,] dDataArray = new double[10, 2];
}
Now I have a function that stream the text file line by line by having the number of rows and index of the array:
using (StreamReader sr = new StreamReader(filename))
{
double[] dx = new double[lines]; //lines store number of rows
double[] dy = new double[lines]; //lines store number of rows
for (long li = 0; li < lines; li++)
{
dx[li] = GlobalDataClass.dDataArray[li, 0];
dy[li] = GlobalDataClass.dDataArray[li, 1];
}
}
My text file will be like:
1,2
2,3
3,4
5,6
Now how to have the output matrix like:
dx[1] [0,0] = 1
dy[1] [0,1] = 2
and so on.
For create multidimensional array, you can use list of list:
List<List<string>> ls = new List<List<string>>();
var filename="aa.txt";
StreamReader sr = new StreamReader(filename);
while (!sr.EndOfStream)
{
var line = sr.ReadLine();
var element = line.Split(',');
List<string> temp = new List<string>();
foreach (var item in element)
{
temp.Add(item);
}
ls.Add(temp);
}
In this code, every line may have many element (>2).
you can read the file and split each line at the comma, like this:
StreamReader sr = new StreamReader("MyNumbers.txt");
String line;
String[] lineSeperate;
line = sr.ReadLine();
lineSeperate = line.Split(',');
now, dx[index] = lineSeperate[0] and dy[index]=lineSeperate[1]
Edit
You need to convert from String to double:
dx[0] = double.Parse(lineSeperate[0]);
dy[0] = double.Parse(lineSeperate[1]);
I want to create a gif file with several frames.
I want to use the Method which Microsoft support--Image.SaveAdd
But I don't know how to set the EncoderParameters Paramater to make up a gif file.
I can't find documents to refer. So how to create a gif file with Image.SaveAdd
Probably, too late to be useful for the original poster, but I managed to create a proper gif using just System.Drawing. The code below is based on jschroedl's answer, but also sets the frame delays and number of animation loops.
// Gdi+ constants absent from System.Drawing.
const int PropertyTagFrameDelay = 0x5100;
const int PropertyTagLoopCount = 0x5101;
const short PropertyTagTypeLong = 4;
const short PropertyTagTypeShort = 3;
const inr UintBytes = 4;
//...
var gifEncoder = GetEncoder(ImageFormat.Gif);
// Params of the first frame.
var encoderParams1 = new EncoderParameters(1);
encoderParams1.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
// Params of other frames.
var encoderParamsN = new EncoderParameters(1);
encoderParamsN.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.FrameDimensionTime);
// Params for the finalizing call.
var encoderParamsFlush = new EncoderParameters(1);
encoderParamsFlush.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.Flush);
// PropertyItem for the frame delay (apparently, no other way to create a fresh instance).
var frameDelay = (PropertyItem)FormatterServices.GetUninitializedObject(typeof(PropertyItem));
frameDelay.Id = PropertyTagFrameDelay;
frameDelay.Type = PropertyTagTypeLong;
// Length of the value in bytes.
frameDelay.Len = Bitmaps.Count * UintBytes;
// The value is an array of 4-byte entries: one per frame.
// Every entry is the frame delay in 1/100-s of a second, in little endian.
frameDelay.Value = new byte[Bitmaps.Count * UintBytes];
// E.g., here, we're setting the delay of every frame to 1 second.
var frameDelayBytes = BitConverter.GetBytes((uint)100);
for (int j = 0; j < Bitmaps.Count; ++j)
Array.Copy(frameDelayBytes, 0, frameDelay.Value, j * UintBytes, UintBytes);
// PropertyItem for the number of animation loops.
var loopPropertyItem = (PropertyItem)FormatterServices.GetUninitializedObject(typeof(PropertyItem));
loopPropertyItem.Id = PropertyTagLoopCount;
loopPropertyItem.Type = PropertyTagTypeShort;
loopPropertyItem.Len = 1;
// 0 means to animate forever.
loopPropertyItem.Value = BitConverter.GetBytes((ushort)0);
using (var stream = new FileStream("animation.gif", FileMode.Create))
{
bool first = true;
Bitmap firstBitmap = null;
// Bitmaps is a collection of Bitmap instances that'll become gif frames.
foreach (var bitmap in Bitmaps)
{
if (first)
{
firstBitmap = bitmap;
firstBitmap.SetPropertyItem(frameDelay);
firstBitmap.SetPropertyItem(loopPropertyItem);
firstBitmap.Save(stream, gifEncoder, encoderParams1);
first = false;
}
else
{
firstBitmap.SaveAdd(bitmap, encoderParamsN);
}
}
firstBitmap.SaveAdd(encoderParamsFlush);
}
// ...
private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
I had success with these parameters. img1,2,3,4... are the images I want to combine.
ULONG parameterValue;
EncoderParameters encoderParameters;
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderSaveFlag;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
encoderParameters.Parameter[0].Value = ¶meterValue;
// Save the first frame
parameterValue = EncoderValueMultiFrame;
rc = img1->Save(L"Output.gif", &encoderClsid, &encoderParameters);
assert(rc == Ok);
// Add the second frame
parameterValue = EncoderValueFrameDimensionTime;
rc = img1->SaveAdd(img2, &encoderParameters);
assert(rc == Ok);
// etc...adding frames img3,4,5...
// Done...
parameterValue = EncoderValueFlush;
rc = img1->SaveAdd(&encoderParameters);
assert(rc == Ok);
Edit: I just realized that you asked for C# and I have C++ code. Hopefully the parameters still apply.
If you want create gif with many picture you can use ngif. see this
//you should replace filepath
String [] imageFilePaths = new String[]{"c:\\01.png","c:\\02.png","c:\\03.png"};
String outputFilePath = "c:\\test.gif";
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.Start( outputFilePath );
e.SetDelay(500);
//-1:no repeat,0:always repeat
e.SetRepeat(0);
for (int i = 0, count = imageFilePaths.Length; i < count; i++ )
{
e.AddFrame( Image.FromFile( imageFilePaths[i] ) );
}
e.Finish();
/* extract Gif */
string outputPath = "c:\\";
GifDecoder gifDecoder = new GifDecoder();
gifDecoder.Read( "c:\\test.gif" );
for ( int i = 0, count = gifDecoder.GetFrameCount(); i < count; i++ )
{
Image frame = gifDecoder.GetFrame( i ); // frame i
frame.Save( outputPath + Guid.NewGuid().ToString()
+ ".png", ImageFormat.Png );
}
I have two text files files (TXT) which contain over 2 million distinct file names. I want to loop through all the names in the first file and find those that are also present in the second text file.
I have tried looping through the StreamReader but it takes a lot of time. I also tried the code below, but it still takes too much time.
StreamReader first = new StreamReader(path);
string strFirst = first.ReadToEnd();
string[] strarrFirst = strFirst.Split('\n');
bool found = false;
StreamReader second = new StreamReader(path2);
string str = second.ReadToEnd();
string[] strarrSecond = str.Split('\n');
for (int j = 0; j < (strarrFirst.Length); j++)
{
found = false;
for (int i = 0; i < (strarrSecond .Length); i++)
{
if (strarrFirst[j] == strarrSecond[i])
{
found = true;
break;
}
}
if (!found)
{
Console.WriteLine(strarrFirst[j]);
}
}
What is a good way to compare the files?
How about this:
var commonNames = File.ReadLines(path).Intersect(File.ReadLines(path2));
That's O(N + M) instead of your current solution which tests every line in the first file with every line in the second file - O(N * M).
That's assuming you're using .NET 4. Otherwise, you could use File.ReadAllLines, but that will read the whole file into memory. Or you could write the equivalent of File.ReadLines yourself - it's not terribly hard.
Ultimately you're likely to be limited by file IO by the time you've got rid of the O(N * M) problem in your current code - there's not much way to get round that.
EDIT: For .NET 2, first let's implement something like ReadLines:
public static IEnumerable<string> ReadLines(string file)
{
using (TextReader reader = File.OpenText(file))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Now we really want to use a HashSet<T>, but that wasn't in .NET 2 - so let's use Dictionary<TKey, TValue> instead:
Dictionary<string, string> map = new Dictionary<string, string>();
foreach (string line in ReadLines(path))
{
map[line] = line;
}
List<string> intersection = new List<string>();
foreach (string line in ReadLines(path2))
{
if (map.ContainsKey(line))
{
intersection.Add(line);
}
}
Try something like this to speed it up a bit ...
var path = string.Empty;
var path2 = string.Empty;
var strFirst = string.Empty;
var str = string.Empty;
var strarrFirst = new List<string>();
var strarrSecond = new List<string>();
using (var first = new StreamReader(path))
{
strFirst = first.ReadToEnd();
}
using (var second = new StreamReader(path2))
{
str = second.ReadToEnd();
}
strarrFirst.AddRange(strFirst.Split('\n'));
strarrSecond.AddRange(str.Split('\n'));
strarrSecond.Sort();
foreach(var value in strarrFirst)
{
var found = strarrSecond.BinarySearch(value) >= 0;
if (!found) Console.WriteLine(value);
}
Just for fun, I've tried Jon Skeet method and own:
var guidArray = Enumerable.Range(0, 1000000).Select(x => Guid.NewGuid().ToString()).ToList();
string path = "first.txt";
File.WriteAllLines(path, guidArray);
string path2 = "second.txt";
File.WriteAllLines(path2, guidArray.Select(x=>DateTime.UtcNow.Ticks % 2 == 0 ? x : Guid.NewGuid().ToString()));
var start = DateTime.Now;
var commonNames = File.ReadLines(path).Intersect(File.ReadLines(path2)).ToList();
Console.WriteLine((DateTime.Now - start).TotalMilliseconds);
start = DateTime.Now;
var lines = File.ReadAllLines(path);
var hashset = new HashSet<string>(lines);
var lines2 = File.ReadAllLines(path2);
var result = lines2.Where(hashset.Contains).ToList();
Console.WriteLine((DateTime.Now - start).TotalMilliseconds);
Console.ReadKey();
And Skeet's method was tiny bit faster (1453.0831 vs 1488.0851, iDevForFun method was quite slow - 12791.7316), so i think under layers should happen same thing as I was trying to do manually with hashset.
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;
}
}
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!