1388 {
1389 using (var reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
1390 {
1391
1392 byte[] magic = reader.ReadBytes(6);
1393 string magicString = Encoding.ASCII.GetString(magic);
1394 if (magicString != "?NUMPY")
1395 {
1396 throw new InvalidOperationException("Invalid .npy file.");
1397 }
1398
1399
1400 reader.BaseStream.Seek(2, SeekOrigin.Current);
1401
1402
1403 byte[] headerLengthBytes = reader.ReadBytes(2);
1404 int headerLength = BitConverter.ToInt16(headerLengthBytes, 0);
1405
1406
1407 byte[] headerBytes = reader.ReadBytes(headerLength);
1408 string headerString = Encoding.ASCII.GetString(headerBytes).Replace("True", "true").Replace("False", "false").Replace("(", "[").Replace(")", "]");
1409
1410
1411 var settings = new JsonSerializerSettings
1412 {
1413 ContractResolver = new CamelCasePropertyNamesContractResolver()
1414 };
1415
1416
1417 NpyHeader header = JsonConvert.DeserializeObject<NpyHeader>(headerString, settings);
1418 var shape = header.shape;
1419 var dtype = header.descr;
1420 NpyDataType type = GetNpyTypeEnum(dtype);
1421
1422
1423 int totalElements = shape.Aggregate(1, (acc, dim) => acc * dim);
1424
1425
1427 int dataSize = totalElements * elementSize;
1428
1429
1430 byte[] dataBytes = reader.ReadBytes(dataSize);
1431
1432
1433 Array data = null;
1434 switch (type)
1435 {
1436 case NpyDataType.UInt8:
1437 data = new byte[dataBytes.Length];
1438 Buffer.BlockCopy(dataBytes, 0, data, 0, dataBytes.Length);
1439 break;
1440
1441 case NpyDataType.Int8:
1442 data = new sbyte[dataBytes.Length];
1443 Buffer.BlockCopy(dataBytes, 0, data, 0, dataBytes.Length);
1444 break;
1445
1446 case NpyDataType.UInt16:
1447 data = new ushort[totalElements];
1448 for (int i = 0; i < data.Length; i++)
1449 {
1450 data.SetValue(BitConverter.ToUInt16(dataBytes, i * 2), i);
1451 }
1452 break;
1453
1454 case NpyDataType.Int16:
1455 data = new short[totalElements];
1456 for (int i = 0; i < data.Length; i++)
1457 {
1458 data.SetValue(BitConverter.ToInt16(dataBytes, i * 2), i);
1459 }
1460 break;
1461
1462 case NpyDataType.UInt32:
1463 data = new uint[totalElements];
1464 for (int i = 0; i < data.Length; i++)
1465 {
1466 data.SetValue(BitConverter.ToUInt32(dataBytes, i * 4), i);
1467 }
1468 break;
1469
1470 case NpyDataType.Int32:
1471 data = new int[totalElements];
1472 for (int i = 0; i < data.Length; i++)
1473 {
1474 data.SetValue(BitConverter.ToInt32(dataBytes, i * 4), i);
1475 }
1476 break;
1477
1478 case NpyDataType.UInt64:
1479 data = new ulong[totalElements];
1480 for (int i = 0; i < data.Length; i++)
1481 {
1482 data.SetValue(BitConverter.ToUInt64(dataBytes, i * 8), i);
1483 }
1484 break;
1485
1486 case NpyDataType.Int64:
1487 data = new long[totalElements];
1488 for (int i = 0; i < data.Length; i++)
1489 {
1490 data.SetValue(BitConverter.ToInt64(dataBytes, i * 8), i);
1491 }
1492 break;
1493
1494 case NpyDataType.Float16:
1495
1496
1497 break;
1498
1499 case NpyDataType.Float32:
1500 data = new float[totalElements];
1501 for (int i = 0; i < data.Length; i++)
1502 {
1503 data.SetValue(BitConverter.ToSingle(dataBytes, i * 4), i);
1504 }
1505 break;
1506
1507 case NpyDataType.Float64:
1508 data = new double[totalElements];
1509 for (int i = 0; i < data.Length; i++)
1510 {
1511 data.SetValue(BitConverter.ToDouble(dataBytes, i * 8), i);
1512 }
1513 break;
1514
1515 case NpyDataType.Complex64:
1516 data = new (float, float)[totalElements];
1517 for (int i = 0; i < data.Length; i++)
1518 {
1519 var real = BitConverter.ToSingle(dataBytes, i * 8);
1520 var imaginary = BitConverter.ToSingle(dataBytes, i * 8 + 4);
1521 data.SetValue((real, imaginary), i);
1522 }
1523 break;
1524
1525 case NpyDataType.Complex128:
1526 data = new (double, double)[totalElements];
1527 for (int i = 0; i < data.Length; i++)
1528 {
1529 var real = BitConverter.ToDouble(dataBytes, i * 16);
1530 var imaginary = BitConverter.ToDouble(dataBytes, i * 16 + 8);
1531 data.SetValue((real, imaginary), i);
1532 }
1533 break;
1534
1535 default:
1536 throw new ArgumentException("Unsupported NpyDataType", nameof(type));
1537 }
1538
1539 return (shape, type, data);
1540 }
1541 }
static int GetElementSize(NpyDataType type)
Helper function to get the size of the elements based on dtype.
Definition Bio.cs:1548