BioLib  3.6.2
A GUI-less version of Bio .NET library for editing & annotating various microscopy image formats.
Loading...
Searching...
No Matches
BioLib.NumPy Class Reference

Classes

class  NpyHeader
 

Public Types

enum  NpyDataType {
  UInt8 = 1 , Int8 = 2 , UInt16 = 3 , Int16 = 4 ,
  UInt32 = 5 , Int32 = 6 , UInt64 = 7 , Int64 = 8 ,
  Float16 = 9 , Float32 = 10 , Float64 = 11 , Complex64 = 12 ,
  Complex128 = 13
}
 

Static Public Member Functions

static string GetNpyTypeString (NpyDataType type)
 
static NpyDataType GetNpyTypeEnum (string type)
 
static void SaveNumPy (BioImage b, string file)
 
static TArray ConvertToMultidimensional< T, TArray > (Array flatArray, int[] shape)
 Converts a flat array into a multi-dimensional array based on the given shape.
 
static Array ReadNpyFile (string filePath)
 
static int GetElementSize (NpyDataType type)
 Helper function to get the size of the elements based on dtype.
 
static T ConvertJaggedArray< T > (Array jaggedArray)
 
static T CreateJaggedArray< T > (int[] shape, T[] data, int dimension)
 
static Array ConvertBytesToTypedArray (byte[] data, NpyDataType dataType)
 

Static Public Attributes

static int []
 
static NpyDataType
 

Detailed Description

Definition at line 2203 of file Bio.cs.

Member Enumeration Documentation

◆ NpyDataType

enum BioLib.NumPy.NpyDataType

Definition at line 2205 of file Bio.cs.

2206 {
2207 // Integer types
2208 UInt8 = 1, // |u1
2209 Int8 = 2, // |i1
2210 UInt16 = 3, // |u2
2211 Int16 = 4, // |i2
2212 UInt32 = 5, // |u4
2213 Int32 = 6, // |i4
2214 UInt64 = 7, // |u8
2215 Int64 = 8, // |i8
2216
2217 // Floating point types
2218 Float16 = 9, // |f2
2219 Float32 = 10, // |f4
2220 Float64 = 11, // |f8
2221
2222 // Complex number types (optional depending on your use case)
2223 Complex64 = 12, // |c8
2224 Complex128 = 13 // |c16
2225 }

Member Function Documentation

◆ ConvertBytesToTypedArray()

static Array BioLib.NumPy.ConvertBytesToTypedArray ( byte[] data,
NpyDataType dataType )
static

Definition at line 2720 of file Bio.cs.

2721 {
2722 switch (dataType)
2723 {
2724 case NpyDataType.UInt8:
2725 return ConvertByteArrayToUInt8(data);
2726 case NpyDataType.Int8:
2727 return ConvertByteArrayToInt8(data);
2728 case NpyDataType.UInt16:
2729 return ConvertByteArrayToUInt16(data);
2730 case NpyDataType.Int16:
2731 return ConvertByteArrayToInt16(data);
2732 case NpyDataType.UInt32:
2733 return ConvertByteArrayToUInt32(data);
2734 case NpyDataType.Int32:
2735 return ConvertByteArrayToInt32(data);
2736 case NpyDataType.UInt64:
2737 return ConvertByteArrayToUInt64(data);
2738 case NpyDataType.Int64:
2739 return ConvertByteArrayToInt64(data);
2740 case NpyDataType.Float16:
2741 return ConvertByteArrayToFloat16(data);
2742 case NpyDataType.Float32:
2743 return ConvertByteArrayToFloat32(data);
2744 case NpyDataType.Float64:
2745 return ConvertByteArrayToFloat64(data);
2746 case NpyDataType.Complex64:
2747 return ConvertByteArrayToComplex64(data);
2748 case NpyDataType.Complex128:
2749 return ConvertByteArrayToComplex128(data);
2750 default:
2751 throw new ArgumentException("Unsupported data type", nameof(dataType));
2752 }
2753 }

◆ ConvertJaggedArray< T >()

static T BioLib.NumPy.ConvertJaggedArray< T > ( Array jaggedArray)
static

Definition at line 2627 of file Bio.cs.

2628 {
2629 // Ensure the provided array is of the correct jagged array type
2630 if (jaggedArray is int[][] jagged)
2631 {
2632 int rows = jagged.Length;
2633 int cols = jagged[0].Length;
2634
2635 // Create an instance of the desired 2D array using reflection
2636 T result = (T)Activator.CreateInstance(typeof(T), new object[] { rows, cols });
2637
2638 // Copy values from jagged array to the newly created 2D array
2639 for (int i = 0; i < rows; i++)
2640 {
2641 for (int j = 0; j < cols; j++)
2642 {
2643 // Use reflection to set the value in the result array
2644 var element = result.GetType().GetElementType();
2645 result.GetType().GetMethod("SetValue").Invoke(result, new object[] { jagged[i][j], i, j });
2646 }
2647 }
2648
2649 return result;
2650 }
2651
2652 throw new InvalidCastException("The input array is not of the expected type.");
2653 }

◆ ConvertToMultidimensional< T, TArray >()

static TArray BioLib.NumPy.ConvertToMultidimensional< T, TArray > ( Array flatArray,
int[] shape )
static

Converts a flat array into a multi-dimensional array based on the given shape.

Template Parameters
TType of the elements in the array.
TArrayType of the target multi-dimensional array.
Parameters
flatArrayThe flat array containing the data.
shapeThe shape of the target multi-dimensional array.
Returns
The multi-dimensional array.

Definition at line 2387 of file Bio.cs.

2388 {
2389 if (flatArray.Length != shape.Aggregate(1, (a, b) => a * b))
2390 throw new ArgumentException("The shape does not match the length of the flat array.");
2391
2392 var result = (Array)Array.CreateInstance(typeof(T), shape);
2393
2394 int[] indices = new int[shape.Length];
2395 for (int i = 0; i < flatArray.Length; i++)
2396 {
2397 // Compute the multi-dimensional indices
2398 int offset = i;
2399 for (int j = shape.Length - 1; j >= 0; j--)
2400 {
2401 indices[j] = offset % shape[j];
2402 offset /= shape[j];
2403 }
2404
2405 // Set the value in the multi-dimensional array
2406 result.SetValue(flatArray.GetValue(i), indices);
2407 }
2408
2409 return (TArray)(object)result;
2410 }

◆ CreateJaggedArray< T >()

static T BioLib.NumPy.CreateJaggedArray< T > ( int[] shape,
T[] data,
int dimension )
static
Type Constraints
T :struct 

Definition at line 2655 of file Bio.cs.

2655 : struct
2656 {
2657 // Base case: if we reached the last dimension, return the data array for that dimension
2658 if (dimension == shape.Length - 1)
2659 {
2660 // Create a 2D array for the last dimension
2661 T[,] array = (T[,])Activator.CreateInstance(typeof(T[,]), shape[dimension], data.Length / shape[dimension]);
2662 Array.Copy(data, array, data.Length); // Copy data into the array
2663 return (T)(object)array; // Cast to T (we will handle this later)
2664 }
2665
2666 // Recursive case: create jagged array for higher dimensions
2667 int subDimensionSize = shape[dimension + 1];
2668 int firstDimLength = shape[dimension];
2669
2670 // Create a jagged array for the current dimension
2671 Array jaggedArray = Array.CreateInstance(typeof(Array), shape[dimension]);
2672
2673 int index = 0;
2674 for (int i = 0; i < firstDimLength; i++)
2675 {
2676 // Recursively create the sub-arrays
2677 var subArray = CreateJaggedArray(shape, data.Skip(index).Take(subDimensionSize).ToArray(), dimension + 1);
2678 jaggedArray.SetValue(subArray, i); // Set the sub-array at index
2679 index += subDimensionSize;
2680 }
2681
2682 // Return the jagged array
2683 return (T)Convert.ChangeType(jaggedArray, typeof(T)); // Use Convert.ChangeType to cast System.Array to T
2684 }

◆ GetElementSize()

static int BioLib.NumPy.GetElementSize ( NpyDataType type)
static

Helper function to get the size of the elements based on dtype.

Parameters
dtype
Returns

Definition at line 2587 of file Bio.cs.

2588 {
2589 switch (type)
2590 {
2591 case NpyDataType.UInt8:
2592 case NpyDataType.Int8:
2593 return 1; // 1 byte for UInt8 and Int8
2594
2595 case NpyDataType.UInt16:
2596 case NpyDataType.Int16:
2597 return 2; // 2 bytes for UInt16 and Int16
2598
2599 case NpyDataType.UInt32:
2600 case NpyDataType.Int32:
2601 return 4; // 4 bytes for UInt32 and Int32
2602
2603 case NpyDataType.UInt64:
2604 case NpyDataType.Int64:
2605 return 8; // 8 bytes for UInt64 and Int64
2606
2607 case NpyDataType.Float16:
2608 return 2; // 2 bytes for Float16
2609
2610 case NpyDataType.Float32:
2611 return 4; // 4 bytes for Float32
2612
2613 case NpyDataType.Float64:
2614 return 8; // 8 bytes for Float64
2615
2616 case NpyDataType.Complex64:
2617 return 8; // 8 bytes for Complex64 (2 * Float32)
2618
2619 case NpyDataType.Complex128:
2620 return 16; // 16 bytes for Complex128 (2 * Float64)
2621
2622 default:
2623 throw new ArgumentException("Unsupported NpyDataType", nameof(type));
2624 }
2625 }

◆ GetNpyTypeEnum()

static NpyDataType BioLib.NumPy.GetNpyTypeEnum ( string type)
static

Definition at line 2260 of file Bio.cs.

2261 {
2262 switch (type)
2263 {
2264 case "|u1":
2265 return NpyDataType.UInt8;
2266 case "|i1":
2267 return NpyDataType.Int8;
2268 case "|u2":
2269 return NpyDataType.UInt16;
2270 case "|i2":
2271 return NpyDataType.Int16;
2272 case "|u4":
2273 return NpyDataType.UInt32;
2274 case "|i4":
2275 return NpyDataType.Int32;
2276 case "|u8":
2277 return NpyDataType.UInt64;
2278 case "|i8":
2279 return NpyDataType.Int64;
2280 case "|f2":
2281 return NpyDataType.Float16;
2282 case "|f4":
2283 return NpyDataType.Float32;
2284 case "|f8":
2285 return NpyDataType.Float64;
2286 case "|c8":
2287 return NpyDataType.Complex64;
2288 case "|c16":
2289 return NpyDataType.Complex128;
2290 case "<f4":
2291 return NpyDataType.Float32;
2292 case "<i4":
2293 return NpyDataType.Int32;
2294 default:
2295 throw new ArgumentException("Unsupported numpy type string", nameof(type));
2296 }
2297 }

◆ GetNpyTypeString()

static string BioLib.NumPy.GetNpyTypeString ( NpyDataType type)
static

Definition at line 2226 of file Bio.cs.

2227 {
2228 switch (type)
2229 {
2230 case NpyDataType.UInt8:
2231 return "|u1";
2232 case NpyDataType.Int8:
2233 return "|i1";
2234 case NpyDataType.UInt16:
2235 return "|u2";
2236 case NpyDataType.Int16:
2237 return "|i2";
2238 case NpyDataType.UInt32:
2239 return "|u4";
2240 case NpyDataType.Int32:
2241 return "|i4";
2242 case NpyDataType.UInt64:
2243 return "|u8";
2244 case NpyDataType.Int64:
2245 return "|i8";
2246 case NpyDataType.Float16:
2247 return "|f2";
2248 case NpyDataType.Float32:
2249 return "|f4";
2250 case NpyDataType.Float64:
2251 return "|f8";
2252 case NpyDataType.Complex64:
2253 return "|c8";
2254 case NpyDataType.Complex128:
2255 return "|c16";
2256 default:
2257 throw new ArgumentException("Unsupported NpyDataType", nameof(type));
2258 }
2259 }

◆ ReadNpyFile()

static Array BioLib.NumPy.ReadNpyFile ( string filePath)
static

Definition at line 2426 of file Bio.cs.

2427 {
2428 using (var reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
2429 {
2430 // Verify .npy magic string
2431 byte[] magic = reader.ReadBytes(6);
2432 string magicString = Encoding.ASCII.GetString(magic);
2433 if (magicString != "?NUMPY")
2434 {
2435 throw new InvalidOperationException("Invalid .npy file.");
2436 }
2437
2438 // Skip the version information (2 bytes)
2439 reader.BaseStream.Seek(2, SeekOrigin.Current);
2440
2441 // Read the header length (2 bytes)
2442 byte[] headerLengthBytes = reader.ReadBytes(2);
2443 int headerLength = BitConverter.ToInt16(headerLengthBytes, 0);
2444
2445 // Read the header bytes
2446 byte[] headerBytes = reader.ReadBytes(headerLength);
2447 string headerString = Encoding.ASCII.GetString(headerBytes).Replace("True", "true").Replace("False", "false").Replace("(", "[").Replace(")", "]");
2448
2449 // Configure Json.NET to handle camel case
2450 var settings = new JsonSerializerSettings
2451 {
2452 ContractResolver = new CamelCasePropertyNamesContractResolver()
2453 };
2454
2455 // Deserialize the JSON string into an object of type NpyHeader
2456 NpyHeader header = JsonConvert.DeserializeObject<NpyHeader>(headerString, settings);
2457 var shape = header.shape;
2458 var dtype = header.descr;
2459 NpyDataType type = GetNpyTypeEnum(dtype);
2460
2461 // Calculate the total number of elements in the array
2462 int totalElements = shape.Aggregate(1, (acc, dim) => acc * dim); // Multiply all dimensions
2463
2464 // Calculate the data size based on the number of elements and element size
2465 int elementSize = GetElementSize(type);
2466 int dataSize = totalElements * elementSize;
2467
2468 // Read the data bytes
2469 byte[] dataBytes = reader.ReadBytes(dataSize);
2470
2471 // Convert the byte array to the proper data type array
2472 Array data = null;
2473 switch (type)
2474 {
2475 case NpyDataType.UInt8:
2476 data = new byte[dataBytes.Length];
2477 Buffer.BlockCopy(dataBytes, 0, data, 0, dataBytes.Length);
2478 break;
2479
2480 case NpyDataType.Int8:
2481 data = new sbyte[dataBytes.Length];
2482 Buffer.BlockCopy(dataBytes, 0, data, 0, dataBytes.Length);
2483 break;
2484
2485 case NpyDataType.UInt16:
2486 data = new ushort[totalElements]; // Using totalElements for multidimensional support
2487 for (int i = 0; i < data.Length; i++)
2488 {
2489 data.SetValue(BitConverter.ToUInt16(dataBytes, i * 2), i);
2490 }
2491 break;
2492
2493 case NpyDataType.Int16:
2494 data = new short[totalElements];
2495 for (int i = 0; i < data.Length; i++)
2496 {
2497 data.SetValue(BitConverter.ToInt16(dataBytes, i * 2), i);
2498 }
2499 break;
2500
2501 case NpyDataType.UInt32:
2502 data = new uint[totalElements];
2503 for (int i = 0; i < data.Length; i++)
2504 {
2505 data.SetValue(BitConverter.ToUInt32(dataBytes, i * 4), i);
2506 }
2507 break;
2508
2509 case NpyDataType.Int32:
2510 data = new int[totalElements];
2511 for (int i = 0; i < data.Length; i++)
2512 {
2513 data.SetValue(BitConverter.ToInt32(dataBytes, i * 4), i);
2514 }
2515 break;
2516
2517 case NpyDataType.UInt64:
2518 data = new ulong[totalElements];
2519 for (int i = 0; i < data.Length; i++)
2520 {
2521 data.SetValue(BitConverter.ToUInt64(dataBytes, i * 8), i);
2522 }
2523 break;
2524
2525 case NpyDataType.Int64:
2526 data = new long[totalElements];
2527 for (int i = 0; i < data.Length; i++)
2528 {
2529 data.SetValue(BitConverter.ToInt64(dataBytes, i * 8), i);
2530 }
2531 break;
2532
2533 case NpyDataType.Float16:
2534 // Convert each 2-byte segment to Float16 (not directly supported by BitConverter)
2535 // You'll need a custom method to handle Float16 conversion
2536 break;
2537
2538 case NpyDataType.Float32:
2539 data = new float[totalElements];
2540 for (int i = 0; i < data.Length; i++)
2541 {
2542 data.SetValue(BitConverter.ToSingle(dataBytes, i * 4), i);
2543 }
2544 break;
2545
2546 case NpyDataType.Float64:
2547 data = new double[totalElements];
2548 for (int i = 0; i < data.Length; i++)
2549 {
2550 data.SetValue(BitConverter.ToDouble(dataBytes, i * 8), i);
2551 }
2552 break;
2553
2554 case NpyDataType.Complex64:
2555 data = new (float, float)[totalElements];
2556 for (int i = 0; i < data.Length; i++)
2557 {
2558 var real = BitConverter.ToSingle(dataBytes, i * 8);
2559 var imaginary = BitConverter.ToSingle(dataBytes, i * 8 + 4);
2560 data.SetValue((real, imaginary), i);
2561 }
2562 break;
2563
2564 case NpyDataType.Complex128:
2565 data = new (double, double)[totalElements];
2566 for (int i = 0; i < data.Length; i++)
2567 {
2568 var real = BitConverter.ToDouble(dataBytes, i * 16);
2569 var imaginary = BitConverter.ToDouble(dataBytes, i * 16 + 8);
2570 data.SetValue((real, imaginary), i);
2571 }
2572 break;
2573
2574 default:
2575 throw new ArgumentException("Unsupported NpyDataType", nameof(type));
2576 }
2577
2578 return (shape, type, data);
2579 }
2580 }
static int GetElementSize(NpyDataType type)
Helper function to get the size of the elements based on dtype.
Definition Bio.cs:2587

◆ SaveNumPy()

static void BioLib.NumPy.SaveNumPy ( BioImage b,
string file )
static

Definition at line 2309 of file Bio.cs.

2310 {
2311 float[] fs = new float[b.SizeT * b.SizeZ * b.SizeC * b.SizeX * b.SizeY];
2312 // Fill the flattened array
2313 int index = 0;
2314 for (int t = 0; t < b.SizeT; t++)
2315 {
2316 for (int z = 0; z < b.SizeZ; z++)
2317 {
2318 for (int c = 0; c < b.SizeC; c++)
2319 {
2320 for (int y = 0; y < b.SizeY; y++)
2321 {
2322 for (int x = 0; x < b.SizeX; x++)
2323 {
2324 fs[index++] = b.Buffers[b.Coords[z, c, t]].GetValue(x, y);
2325 }
2326 }
2327 }
2328 }
2329 }
2330 SaveFloatArrayAsNpy(file, fs, new int[] { b.SizeT, b.SizeC, b.SizeZ, b.SizeX, b.SizeY });
2331 }

Member Data Documentation

◆ int

BioLib.NumPy.int[]
static

Definition at line 2426 of file Bio.cs.

◆ NpyDataType

BioLib.NumPy.NpyDataType
static

Definition at line 2426 of file Bio.cs.


The documentation for this class was generated from the following file: