/// <summary> /// Reads in three-dimensional environmental data from a NetCDF and stores them in the array of values within this instance of EnviroData /// </summary> /// <param name="internalData">The SDS object to get data from</param> /// <param name="dataName">The name of the variable within the NetCDF file</param> /// <param name="latInverted">Whether the latitude values are inverted in the NetCDF file (i.e. large to small values)</param> /// <param name="longInverted">Whether the longitude values are inverted in the NetCDF file (i.e. large to small values)</param> private void EnvironmentListFromNetCDF3D(DataSet internalData, string dataName, bool latInverted, bool longInverted) { // Vector to hold the position in the dimensions of the NetCDF file of the latitude, longitude and third dimensions int[] positions = new int[3]; // Array to store environmental data with latitude as the first dimension and longitude as the second dimension double[,] LatLongArrayUnsorted = new double[_NumLats, _NumLons]; // Check that the requested variable exists in the NetCDF file Debug.Assert(internalData.Variables.Contains(dataName), "Requested variable does not exist in the specified file"); // Check that the environmental variable in the NetCDF file has three dimensions Debug.Assert(internalData.Variables[dataName].Dimensions.Count == 3, "The specified variable in the NetCDF file does not have three dimensions, which is the required number for this method"); // Possible names for the missing value metadata in the NetCDF file string[] SearchStrings = { "missing_value", "MissingValue" }; // Loop over possible names for the missing value metadata until a match is found in the NetCDF file int kk = 0; while ((kk < SearchStrings.Length) & (!internalData.Variables[dataName].Metadata.ContainsKey(SearchStrings[kk]))) kk++; // If a match is found, then set the missing data field equal to the value in the file, otherwise throw an error if (kk < SearchStrings.Length) { _MissingValue = Convert.ToDouble(internalData.Variables[dataName].Metadata[SearchStrings[kk]]); } else { Debug.Fail("No missing data value found for environmental data file: " + internalData.Name.ToString()); } // Possible names for the latitude dimension in the NetCDF file SearchStrings = new string[] { "lat", "Lat", "latitude", "Latitude", "lats", "Lats", "latitudes", "Latitudes", "y" }; // Check which position the latitude dimension is in in the NetCDF file and add this to the vector of positions. If the latitude dimension cannot be // found then throw an error if (SearchStrings.Contains(internalData.Dimensions[0].Name.ToString())) { positions[0] = 1; } else if (SearchStrings.Contains(internalData.Dimensions[1].Name.ToString())) { positions[1] = 1; } else if (SearchStrings.Contains(internalData.Dimensions[2].Name.ToString())) { positions[2] = 1; } else { Debug.Fail("Cannot find a latitude dimension"); } // Possible names for the longitude dimension in the netCDF file SearchStrings = new string[] { "lon", "Lon", "longitude", "Longitude", "lons", "Lons", "long", "Long", "longs", "Longs", "longitudes", "Longitudes", "x" }; // Check which position the latitude dimension is in in the NetCDF file and add this to the vector of positions. If the latitude dimension cannot be // found then throw an error if (SearchStrings.Contains(internalData.Dimensions[0].Name.ToString())) { positions[0] = 2; } else if (SearchStrings.Contains(internalData.Dimensions[1].Name.ToString())) { positions[1] = 2; } else if (SearchStrings.Contains(internalData.Dimensions[2].Name.ToString())) { positions[2] = 2; } else { Debug.Fail("Cannot find a longitude dimension"); } // Possible names for the monthly temporal dimension in the netCDF file SearchStrings = new string[] { "month", "Month", "months", "Months" }; // Check which position the temporal dimension is in in the NetCDF file and add this to the vector of positions. If the temporal dimension cannot be // found then throw an error if (SearchStrings.Contains(internalData.Dimensions[0].Name.ToString())) { positions[0] = 3; } else if (SearchStrings.Contains(internalData.Dimensions[1].Name.ToString())) { positions[1] = 3; } else if (SearchStrings.Contains(internalData.Dimensions[2].Name.ToString())) { positions[2] = 3; } // Check the format of the specified environmental variable if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "single") { // Read the environmental data into a temporary array Single[, ,] TempArray; TempArray = internalData.GetData<Single[, ,]>(dataName); // Revised for speed switch (positions[0]) { case 1: switch (positions[1]) { case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[ii, jj, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[ii, hh, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 2: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[jj, ii, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[jj, hh, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 3: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[hh, ii, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[hh, jj, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } } else if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "double") { // Read the environmental data into a temporary array double[, ,] TempArray; TempArray = internalData.GetData<double[, ,]>(dataName); // Revised for speed switch (positions[0]) { case 1: switch (positions[1]) { case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[ii, jj, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[ii, hh, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 2: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[jj, ii, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[jj, hh, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 3: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[hh, ii, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[hh, jj, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } } else if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "int32") { // Read the environmental data into a temporary array Int32[, ,] TempArray; TempArray = internalData.GetData<Int32[, ,]>(dataName); // Revised for speed switch (positions[0]) { case 1: switch (positions[1]) { case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[ii, jj, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[ii, hh, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 2: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[jj, ii, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[jj, hh, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 3: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[hh, ii, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[hh, jj, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } } else if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "int16") { // Read the environmental data into a temporary array Int16[, ,] TempArray; TempArray = internalData.GetData<Int16[, ,]>(dataName); // Revised for speed switch (positions[0]) { case 1: switch (positions[1]) { case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[ii, jj, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[ii, hh, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 2: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[jj, ii, hh]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 3: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[jj, hh, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; case 3: switch (positions[1]) { case 1: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[hh, ii, jj]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; case 2: // Loop over time steps for (int hh = 0; hh < _NumTimes; hh++) { // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; // Add to the unsorted array of values, transposing the data to be dimensioned by latitude first and // longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = (double)TempArray[hh, jj, ii]; } } // Transpose the environmental data so that they are in ascending order of both latitude and longitude if (latInverted) { if (longInverted) { // Both dimensions inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, LongLengthMinusOne - jj]; } } } else { // Latitude only inverted int LatLengthMinusOne = LatLongArrayUnsorted.GetLength(0) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[LatLengthMinusOne - ii, jj]; } } } } else { if (longInverted) { // Longitude only inverted int LongLengthMinusOne = LatLongArrayUnsorted.GetLength(1) - 1; for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[ii, LongLengthMinusOne - jj]; } } } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } break; default: Debug.Fail("Failure detecting latitude dimension"); break; } } else { // Format of environmental data not recognized so throw an error Debug.Fail("Environmental data are in an unrecognized format"); } // If either latitude or longitude were inverted, then reverse their values in the class fields if (latInverted) { // Temporary vector to store inverted latitude values double[] tempLats = new double[_NumLats]; // Loop over latitude values for (int ii = 0; ii < _NumLats; ii++) { // Invert the values in the temporary vector tempLats[ii] = _Lats[_Lats.Length - 1 - ii]; } // Overwrite the old vector of latitude values with the inverted values _Lats = tempLats; // Reverse the sign on the difference in latitude values between adjacent cells _LatStep = -_LatStep; } if (longInverted) { // Temporary vector to store inverted longitude values double[] tempLongs = new double[_NumLons]; // Loop over longitude values for (int jj = 0; jj < _NumLons; jj++) { // Invert the values in the temporary vector tempLongs[jj] = _Lons[_Lons.Length - 1 - jj]; } // Overwrite the old vector of longitude values with the inverted values _Lons = tempLongs; // Reverse the sign on the difference in longitude values between adjacent cells _LonStep = -_LonStep; } // Check that the increment in both latitudes and longitudes between consecutive grid cells is now positive Debug.Assert(_LatStep > 0.0, "Latitudes are still inverted in an environmental variable stored in EnviroData"); Debug.Assert(_LonStep > 0.0, "Longitudes are still inverted in an environmental variable stored in EnviroData"); }
/// <summary> /// Reads in two-dimensional environmental data from a NetCDF and stores them in the array of values within this instance of EnviroData /// </summary> /// <param name="internalData">The SDS object to get data from</param> /// <param name="dataName">The name of the variable within the NetCDF file</param> /// <param name="latInverted">Whether the latitude values are inverted in the NetCDF file (i.e. large to small values)</param> /// <param name="longInverted">Whether the longitude values are inverted in the NetCDF file (i.e. large to small values)</param> private void EnvironmentListFromNetCDF(DataSet internalData, string dataName, bool latInverted, bool longInverted) { // Vector two hold the position in the dimensions of the NetCDF file of the latitude and longitude dimensions int[] positions = new int[2]; // Array to store environmental data with latitude as the first dimension and longitude as the second dimension double[,] LatLongArrayUnsorted = new double[_NumLats, _NumLons]; // Array to store environmental data as above, but with data in ascending order of both latitude and longitude double[,] LatLongArraySorted = new double[_NumLats, _NumLons]; Console.WriteLine(dataName); // Check that the requested variable exists in the NetCDF file Debug.Assert(internalData.Variables.Contains(dataName), "Requested variable does not exist in the specified file"); // Check that the environmental variable in the NetCDF file has two dimensions Debug.Assert(internalData.Variables[dataName].Dimensions.Count == 2, "The specified variable in the NetCDF file does not have two dimensions, which is the required number for this method"); // Possible names for the missing value metadata in the NetCDF file string[] SearchStrings = { "missing_value", "MissingValue" }; // Loop over possible names for the missing value metadata until a match is found in the NetCDF file int kk = 0; while ((kk < SearchStrings.Length) && (!internalData.Variables[dataName].Metadata.ContainsKey(SearchStrings[kk]))) kk++; // If a match is found, then set the missing data field equal to the value in the file, otherwise throw an error if (kk < SearchStrings.Length) { _MissingValue = Convert.ToDouble(internalData.Variables[dataName].Metadata[SearchStrings[kk]]); } else { Console.WriteLine("No missing data value found for this variable: assigning a value of -9999"); _MissingValue = -9999; } // Possible names for the latitude dimension in the NetCDF file SearchStrings = new string[] { "lat", "Lat", "latitude", "Latitude", "lats", "Lats", "latitudes", "Latitudes", "y", "Y" }; // Check which position the latitude dimension is in in the NetCDF file and add this to the vector of positions. If the latitude dimension cannot be // found then throw an error if (SearchStrings.Contains(internalData.Dimensions[0].Name.ToString())) { positions[0] = 1; } else if (SearchStrings.Contains(internalData.Dimensions[1].Name.ToString())) { positions[1] = 1; } else { Debug.Fail("Cannot find a latitude dimension"); } // Possible names for the longitude dimension in the netCDF file SearchStrings = new string[] { "lon", "Lon", "longitude", "Longitude", "lons", "Lons", "long", "Long", "longs", "Longs", "longitudes", "Longitudes", "x", "X" }; // Check which position the latitude dimension is in in the NetCDF file and add this to the vector of positions. If the latitude dimension cannot be // found then throw an error if (SearchStrings.Contains(internalData.Dimensions[0].Name.ToString())) { positions[0] = 2; } else if (SearchStrings.Contains(internalData.Dimensions[1].Name.ToString())) { positions[1] = 2; } else { Debug.Fail("Cannot find a longitude dimension"); } // Check the format of the specified environmental variable if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "single") { // Read the environmental data into a temporary array Single[,] TempArray; TempArray = internalData.GetData<Single[,]>(dataName); // Convert the data to double format and add to the unsorted array of values, transposing the data to be dimensioned by latitude first and longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[(int)(ii * Convert.ToDouble(positions[0] == 1) + jj * Convert.ToDouble(positions[0] == 2)), (int)(ii * Convert.ToDouble(positions[1] == 1) + jj * Convert.ToDouble(positions[1] == 2))]; } } } else if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "double") { // Read the environmental data into a temporary array double[,] TempArray; TempArray = internalData.GetData<double[,]>(dataName); // Add the data to the unsorted array of values, transposing the data to be dimensioned by latitude first and longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[(int)(ii * Convert.ToDouble(positions[0] == 1) + jj * Convert.ToDouble(positions[0] == 2)), (int)(ii * Convert.ToDouble(positions[1] == 1) + jj * Convert.ToDouble(positions[1] == 2))]; } } } else if (internalData.Variables[dataName].TypeOfData.Name.ToString().ToLower() == "int32") { // Read the environmental data into a temporary array Int32[,] TempArray; TempArray = internalData.GetData<Int32[,]>(dataName); // Convert the data to double format and add to the unsorted array of values, transposing the data to be dimensioned by latitude first and longitude second for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArrayUnsorted[ii, jj] = TempArray[(int)(ii * Convert.ToDouble(positions[0] == 1) + jj * Convert.ToDouble(positions[0] == 2)), (int)(ii * Convert.ToDouble(positions[1] == 1) + jj * Convert.ToDouble(positions[1] == 2))]; } } } else { // Format of environmental data not recognized so throw an error Debug.Fail("Environmental data are in an unrecognized format"); } // Transpose the environmental data so that they are in ascending order of both latitude and longitude for (int ii = 0; ii < _NumLats; ii++) { for (int jj = 0; jj < _NumLons; jj++) { LatLongArraySorted[ii, jj] = LatLongArrayUnsorted[(int)((1 - Convert.ToDouble(latInverted)) * ii + (Convert.ToDouble(latInverted) * (LatLongArrayUnsorted.GetLength(0) - 1 - ii))), (int)((1 - Convert.ToDouble(longInverted)) * jj + (Convert.ToDouble(longInverted) * (LatLongArrayUnsorted.GetLength(1) - 1 - jj)))]; } } // Add the final array to the class field for environmental data values _DataArray.Add(LatLongArraySorted); // If either latitude or longitude were inverted, then reverse their values in the class fields if (latInverted) { // Temporary vector to store inverted latitude values double[] tempLats = new double[_NumLats]; // Loop over latitude values for (int ii = 0; ii < _NumLats; ii++) { // Invert the values in the temporary vector tempLats[ii] = _Lats[_Lats.Length - 1 - ii]; } // Overwrite the old vector of latitude values with the inverted values _Lats = tempLats; // Reverse the sign on the difference in latitude values between adjacent cells _LatStep = -_LatStep; } if (longInverted) { // Temporary vector to store inverted longitude values double[] tempLongs = new double[_NumLons]; // Loop over longitude values for (int jj = 0; jj < _NumLons; jj++) { // Invert the values in the temporary vector tempLongs[jj] = _Lons[_Lons.Length - 1 - jj]; } // Overwrite the old vector of longitude values with the inverted values _Lons = tempLongs; // Reverse the sign on the difference in longitude values between adjacent cells _LonStep = -_LonStep; } // Check that the increment in both latitudes and longitudes between consecutive grid cells is now positive Debug.Assert(_LatStep > 0.0, "Latitudes are still inverted in an environmental variable stored in EnviroData"); Debug.Assert(_LonStep > 0.0, "Longitudes are still inverted in an environmental variable stored in EnviroData"); }