mlarray 0.0.43__tar.gz → 0.0.45__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {mlarray-0.0.43 → mlarray-0.0.45}/PKG-INFO +1 -1
  2. mlarray-0.0.45/examples/example_in_memory_constructors.py +84 -0
  3. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray/mlarray.py +735 -0
  4. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray.egg-info/PKG-INFO +1 -1
  5. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray.egg-info/SOURCES.txt +2 -0
  6. mlarray-0.0.45/tests/test_constructors.py +135 -0
  7. {mlarray-0.0.43 → mlarray-0.0.45}/.github/workflows/workflow.yml +0 -0
  8. {mlarray-0.0.43 → mlarray-0.0.45}/.gitignore +0 -0
  9. {mlarray-0.0.43 → mlarray-0.0.45}/LICENSE +0 -0
  10. {mlarray-0.0.43 → mlarray-0.0.45}/MANIFEST.in +0 -0
  11. {mlarray-0.0.43 → mlarray-0.0.45}/README.md +0 -0
  12. {mlarray-0.0.43 → mlarray-0.0.45}/assets/banner.png +0 -0
  13. {mlarray-0.0.43 → mlarray-0.0.45}/assets/banner.png~ +0 -0
  14. {mlarray-0.0.43 → mlarray-0.0.45}/docs/api.md +0 -0
  15. {mlarray-0.0.43 → mlarray-0.0.45}/docs/cli.md +0 -0
  16. {mlarray-0.0.43 → mlarray-0.0.45}/docs/index.md +0 -0
  17. {mlarray-0.0.43 → mlarray-0.0.45}/docs/optimization.md +0 -0
  18. {mlarray-0.0.43 → mlarray-0.0.45}/docs/schema.md +0 -0
  19. {mlarray-0.0.43 → mlarray-0.0.45}/docs/usage.md +0 -0
  20. {mlarray-0.0.43 → mlarray-0.0.45}/docs/why.md +0 -0
  21. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_asarray.py +0 -0
  22. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_bboxes_only.py +0 -0
  23. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_channel.py +0 -0
  24. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_metadata_only.py +0 -0
  25. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_non_spatial.py +0 -0
  26. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_open.py +0 -0
  27. {mlarray-0.0.43 → mlarray-0.0.45}/examples/example_save_load.py +0 -0
  28. {mlarray-0.0.43 → mlarray-0.0.45}/mkdocs.yml +0 -0
  29. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray/__init__.py +0 -0
  30. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray/cli.py +0 -0
  31. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray/meta.py +0 -0
  32. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray/utils.py +0 -0
  33. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray.egg-info/dependency_links.txt +0 -0
  34. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray.egg-info/entry_points.txt +0 -0
  35. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray.egg-info/requires.txt +0 -0
  36. {mlarray-0.0.43 → mlarray-0.0.45}/mlarray.egg-info/top_level.txt +0 -0
  37. {mlarray-0.0.43 → mlarray-0.0.45}/pyproject.toml +0 -0
  38. {mlarray-0.0.43 → mlarray-0.0.45}/setup.cfg +0 -0
  39. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_asarray.py +0 -0
  40. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_bboxes.py +0 -0
  41. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_create.py +0 -0
  42. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_metadata.py +0 -0
  43. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_open.py +0 -0
  44. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_optimization.py +0 -0
  45. {mlarray-0.0.43 → mlarray-0.0.45}/tests/test_usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlarray
3
- Version: 0.0.43
3
+ Version: 0.0.45
4
4
  Summary: Array format specialized for Machine Learning with Blosc2 backend and standardized metadata.
5
5
  Author-email: Karol Gotkowski <karol.gotkowski@dkfz.de>
6
6
  License: MIT
@@ -0,0 +1,84 @@
1
+ from pathlib import Path
2
+
3
+ import numpy as np
4
+
5
+ from mlarray import MLArray
6
+
7
+
8
+ def main():
9
+ shape = (2, 4, 4)
10
+
11
+ a_empty = MLArray.empty(
12
+ shape=shape,
13
+ dtype=np.float32,
14
+ patch_size=None,
15
+ chunk_size=(1, 4, 4),
16
+ block_size=(1, 2, 2),
17
+ )
18
+ a_empty[...] = np.arange(np.prod(shape), dtype=np.float32).reshape(shape)
19
+
20
+ a_zeros = MLArray.zeros(
21
+ shape=shape,
22
+ dtype=np.float32,
23
+ patch_size=None,
24
+ chunk_size=(1, 4, 4),
25
+ block_size=(1, 2, 2),
26
+ )
27
+ a_ones = MLArray.ones(
28
+ shape=shape,
29
+ dtype=np.float32,
30
+ patch_size=None,
31
+ chunk_size=(1, 4, 4),
32
+ block_size=(1, 2, 2),
33
+ )
34
+ a_full = MLArray.full(
35
+ shape=shape,
36
+ fill_value=5,
37
+ dtype=np.float32,
38
+ patch_size=None,
39
+ chunk_size=(1, 4, 4),
40
+ block_size=(1, 2, 2),
41
+ )
42
+
43
+ a_arange = MLArray.arange(0, 16, 1, shape=(4, 4), patch_size=None)
44
+ a_linspace = MLArray.linspace(
45
+ 0.0, 1.0, num=8, shape=(2, 4), endpoint=False, patch_size=None
46
+ )
47
+
48
+ a_empty_like = MLArray.empty_like(
49
+ a_full, patch_size=None, chunk_size=(1, 4, 4), block_size=(1, 2, 2)
50
+ )
51
+ a_empty_like[...] = 11
52
+ a_zeros_like = MLArray.zeros_like(
53
+ a_full, patch_size=None, chunk_size=(1, 4, 4), block_size=(1, 2, 2)
54
+ )
55
+ a_ones_like = MLArray.ones_like(
56
+ a_full, patch_size=None, chunk_size=(1, 4, 4), block_size=(1, 2, 2)
57
+ )
58
+ a_full_like = MLArray.full_like(
59
+ a_full,
60
+ fill_value=9,
61
+ patch_size=None,
62
+ chunk_size=(1, 4, 4),
63
+ block_size=(1, 2, 2),
64
+ )
65
+
66
+ print("empty sum:", float(a_empty[...].sum()))
67
+ print("zeros sum:", float(a_zeros[...].sum()))
68
+ print("ones sum:", float(a_ones[...].sum()))
69
+ print("full sum:", float(a_full[...].sum()))
70
+ print("arange:", a_arange[...])
71
+ print("linspace:", a_linspace[...])
72
+ print("empty_like unique:", np.unique(a_empty_like[...]))
73
+ print("zeros_like sum:", float(a_zeros_like[...].sum()))
74
+ print("ones_like sum:", float(a_ones_like[...].sum()))
75
+ print("full_like sum:", float(a_full_like[...].sum()))
76
+
77
+ out_path = Path("example_in_memory_constructors_output.mla")
78
+ a_full_like.save(out_path)
79
+ loaded = MLArray(out_path)
80
+ print("saved shape:", loaded.shape, "dtype:", loaded.dtype)
81
+
82
+
83
+ if __name__ == "__main__":
84
+ main()
@@ -328,6 +328,734 @@ class MLArray:
328
328
  self._validate_and_add_meta(self.meta)
329
329
  self._write_metadata()
330
330
 
331
+ @staticmethod
332
+ def _normalize_shape(shape: Union[int, List, Tuple, np.ndarray]) -> Tuple[int, ...]:
333
+ if isinstance(shape, (int, np.integer)):
334
+ return (int(shape),)
335
+ return tuple(int(v) for v in shape)
336
+
337
+ def _resolve_like_input(self, x, dtype, meta):
338
+ if isinstance(x, MLArray):
339
+ if x._store is None or x.meta is None or x.meta._has_array.has_array is False:
340
+ raise TypeError("Input MLArray has no array data loaded.")
341
+ shape = self._normalize_shape(x.shape)
342
+ src_dtype = x.dtype
343
+ if meta is None:
344
+ meta = deepcopy(x.meta)
345
+ elif hasattr(x, "shape") and hasattr(x, "dtype"):
346
+ shape = self._normalize_shape(x.shape)
347
+ src_dtype = x.dtype
348
+ else:
349
+ raise TypeError(
350
+ "x must be an MLArray or an array-like object with shape and dtype."
351
+ )
352
+
353
+ dtype = src_dtype if dtype is None else dtype
354
+ return shape, np.dtype(dtype), meta
355
+
356
+ def _construct_in_memory(
357
+ self,
358
+ shape: Union[int, List, Tuple, np.ndarray],
359
+ dtype: np.dtype,
360
+ store_builder,
361
+ meta: Optional[Union[Dict, Meta]] = None,
362
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
363
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
364
+ block_size: Optional[Union[int, List, Tuple]] = None,
365
+ num_threads: int = 1,
366
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
367
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
368
+ ):
369
+ """Internal generic constructor for in-memory Blosc2-backed MLArrays.
370
+
371
+ Args:
372
+ shape (Union[int, List, Tuple, np.ndarray]): Target array shape.
373
+ dtype (np.dtype): Target dtype.
374
+ store_builder (Callable): Callable receiving normalized kwargs and
375
+ returning a Blosc2 NDArray.
376
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
377
+ the created ``MLArray``. Dict values are stored as
378
+ ``meta.source``.
379
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
380
+ chunk/block optimization. Use ``"default"`` to use the default
381
+ patch size of 192.
382
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
383
+ Ignored when ``patch_size`` is provided.
384
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
385
+ Ignored when ``patch_size`` is provided.
386
+ num_threads (int): Number of threads for Blosc2 operations.
387
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
388
+ parameters. If None, defaults to
389
+ ``{'codec': blosc2.Codec.LZ4HC, 'clevel': 8}``.
390
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
391
+ decompression parameters. If None, defaults to
392
+ ``{'nthreads': num_threads}``.
393
+ """
394
+ shape = self._normalize_shape(shape)
395
+ dtype = np.dtype(dtype)
396
+
397
+ self._validate_and_add_meta(meta, has_array=True)
398
+ spatial_axis_mask = (
399
+ [True] * len(shape)
400
+ if self.meta.spatial.axis_labels is None
401
+ else _spatial_axis_mask(self.meta.spatial.axis_labels)
402
+ )
403
+ self.meta.blosc2 = self._comp_and_validate_blosc2_meta(
404
+ self.meta.blosc2,
405
+ patch_size,
406
+ chunk_size,
407
+ block_size,
408
+ shape,
409
+ dtype.itemsize,
410
+ spatial_axis_mask,
411
+ )
412
+ self.meta._has_array.has_array = True
413
+
414
+ blosc2.set_nthreads(num_threads)
415
+ if cparams is None:
416
+ cparams = {"codec": blosc2.Codec.LZ4HC, "clevel": 8}
417
+ if dparams is None:
418
+ dparams = {"nthreads": num_threads}
419
+
420
+ self._store = store_builder(
421
+ shape=shape,
422
+ dtype=dtype,
423
+ chunks=self.meta.blosc2.chunk_size,
424
+ blocks=self.meta.blosc2.block_size,
425
+ cparams=cparams,
426
+ dparams=dparams,
427
+ )
428
+
429
+ self._update_blosc2_meta()
430
+ self._validate_and_add_meta(self.meta)
431
+
432
+ @classmethod
433
+ def empty(
434
+ cls,
435
+ shape: Union[int, List, Tuple, np.ndarray],
436
+ dtype: np.dtype,
437
+ meta: Optional[Union[Dict, Meta]] = None,
438
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
439
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
440
+ block_size: Optional[Union[int, List, Tuple]] = None,
441
+ num_threads: int = 1,
442
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
443
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
444
+ ):
445
+ """Create an in-memory MLArray with uninitialized values.
446
+
447
+ Args:
448
+ shape (Union[int, List, Tuple, np.ndarray]): Shape of the output
449
+ array.
450
+ dtype (np.dtype): Numpy dtype for the output array.
451
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
452
+ the created ``MLArray``. Dict values are stored as
453
+ ``meta.source``.
454
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
455
+ chunk/block optimization. Use ``"default"`` to use the default
456
+ patch size of 192.
457
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
458
+ Ignored when ``patch_size`` is provided.
459
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
460
+ Ignored when ``patch_size`` is provided.
461
+ num_threads (int): Number of threads for Blosc2 operations.
462
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
463
+ parameters used when writing chunks.
464
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
465
+ decompression parameters used when reading chunks.
466
+
467
+ Returns:
468
+ MLArray: A newly created in-memory MLArray instance.
469
+ """
470
+ class_instance = cls()
471
+ class_instance._construct_in_memory(
472
+ shape=shape,
473
+ dtype=dtype,
474
+ meta=meta,
475
+ patch_size=patch_size,
476
+ chunk_size=chunk_size,
477
+ block_size=block_size,
478
+ num_threads=num_threads,
479
+ cparams=cparams,
480
+ dparams=dparams,
481
+ store_builder=lambda **kwargs: blosc2.empty(**kwargs),
482
+ )
483
+ return class_instance
484
+
485
+ @classmethod
486
+ def zeros(
487
+ cls,
488
+ shape: Union[int, List, Tuple, np.ndarray],
489
+ dtype: np.dtype,
490
+ meta: Optional[Union[Dict, Meta]] = None,
491
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
492
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
493
+ block_size: Optional[Union[int, List, Tuple]] = None,
494
+ num_threads: int = 1,
495
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
496
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
497
+ ):
498
+ """Create an in-memory MLArray filled with zeros.
499
+
500
+ Args:
501
+ shape (Union[int, List, Tuple, np.ndarray]): Shape of the output
502
+ array.
503
+ dtype (np.dtype): Numpy dtype for the output array.
504
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
505
+ the created ``MLArray``.
506
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
507
+ chunk/block optimization.
508
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
509
+ Ignored when ``patch_size`` is provided.
510
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
511
+ Ignored when ``patch_size`` is provided.
512
+ num_threads (int): Number of threads for Blosc2 operations.
513
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
514
+ parameters.
515
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
516
+ decompression parameters.
517
+
518
+ Returns:
519
+ MLArray: A newly created in-memory MLArray instance.
520
+ """
521
+ class_instance = cls()
522
+ class_instance._construct_in_memory(
523
+ shape=shape,
524
+ dtype=dtype,
525
+ meta=meta,
526
+ patch_size=patch_size,
527
+ chunk_size=chunk_size,
528
+ block_size=block_size,
529
+ num_threads=num_threads,
530
+ cparams=cparams,
531
+ dparams=dparams,
532
+ store_builder=lambda **kwargs: blosc2.zeros(**kwargs),
533
+ )
534
+ return class_instance
535
+
536
+ @classmethod
537
+ def ones(
538
+ cls,
539
+ shape: Union[int, List, Tuple, np.ndarray],
540
+ dtype: np.dtype = None,
541
+ meta: Optional[Union[Dict, Meta]] = None,
542
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
543
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
544
+ block_size: Optional[Union[int, List, Tuple]] = None,
545
+ num_threads: int = 1,
546
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
547
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
548
+ ):
549
+ """Create an in-memory MLArray filled with ones.
550
+
551
+ Args:
552
+ shape (Union[int, List, Tuple, np.ndarray]): Shape of the output
553
+ array.
554
+ dtype (np.dtype): Numpy dtype for the output array. If None, uses
555
+ ``blosc2.DEFAULT_FLOAT``.
556
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
557
+ the created ``MLArray``.
558
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
559
+ chunk/block optimization.
560
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
561
+ Ignored when ``patch_size`` is provided.
562
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
563
+ Ignored when ``patch_size`` is provided.
564
+ num_threads (int): Number of threads for Blosc2 operations.
565
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
566
+ parameters.
567
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
568
+ decompression parameters.
569
+
570
+ Returns:
571
+ MLArray: A newly created in-memory MLArray instance.
572
+ """
573
+ dtype = blosc2.DEFAULT_FLOAT if dtype is None else dtype
574
+ class_instance = cls()
575
+ class_instance._construct_in_memory(
576
+ shape=shape,
577
+ dtype=dtype,
578
+ meta=meta,
579
+ patch_size=patch_size,
580
+ chunk_size=chunk_size,
581
+ block_size=block_size,
582
+ num_threads=num_threads,
583
+ cparams=cparams,
584
+ dparams=dparams,
585
+ store_builder=lambda **kwargs: blosc2.ones(**kwargs),
586
+ )
587
+ return class_instance
588
+
589
+ @classmethod
590
+ def full(
591
+ cls,
592
+ shape: Union[int, List, Tuple, np.ndarray],
593
+ fill_value: Union[bytes, int, float, bool],
594
+ dtype: np.dtype = None,
595
+ meta: Optional[Union[Dict, Meta]] = None,
596
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
597
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
598
+ block_size: Optional[Union[int, List, Tuple]] = None,
599
+ num_threads: int = 1,
600
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
601
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
602
+ ):
603
+ """Create an in-memory MLArray filled with ``fill_value``.
604
+
605
+ Args:
606
+ shape (Union[int, List, Tuple, np.ndarray]): Shape of the output
607
+ array.
608
+ fill_value (Union[bytes, int, float, bool]): Fill value used for all
609
+ elements in the output.
610
+ dtype (np.dtype): Numpy dtype for the output array. If None, inferred
611
+ from ``fill_value``.
612
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
613
+ the created ``MLArray``.
614
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
615
+ chunk/block optimization.
616
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
617
+ Ignored when ``patch_size`` is provided.
618
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
619
+ Ignored when ``patch_size`` is provided.
620
+ num_threads (int): Number of threads for Blosc2 operations.
621
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
622
+ parameters.
623
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
624
+ decompression parameters.
625
+
626
+ Returns:
627
+ MLArray: A newly created in-memory MLArray instance.
628
+ """
629
+ if dtype is None:
630
+ if isinstance(fill_value, bytes):
631
+ dtype = np.dtype(f"S{len(fill_value)}")
632
+ else:
633
+ dtype = np.dtype(type(fill_value))
634
+ class_instance = cls()
635
+ class_instance._construct_in_memory(
636
+ shape=shape,
637
+ dtype=dtype,
638
+ meta=meta,
639
+ patch_size=patch_size,
640
+ chunk_size=chunk_size,
641
+ block_size=block_size,
642
+ num_threads=num_threads,
643
+ cparams=cparams,
644
+ dparams=dparams,
645
+ store_builder=lambda **kwargs: blosc2.full(fill_value=fill_value, **kwargs),
646
+ )
647
+ return class_instance
648
+
649
+ @classmethod
650
+ def arange(
651
+ cls,
652
+ start: Union[int, float],
653
+ stop: Optional[Union[int, float]] = None,
654
+ step: Optional[Union[int, float]] = 1,
655
+ dtype: np.dtype = None,
656
+ shape: Optional[Union[int, List, Tuple, np.ndarray]] = None,
657
+ c_order: bool = True,
658
+ meta: Optional[Union[Dict, Meta]] = None,
659
+ patch_size: Optional[Union[int, List, Tuple]] = None,
660
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
661
+ block_size: Optional[Union[int, List, Tuple]] = None,
662
+ num_threads: int = 1,
663
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
664
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
665
+ ):
666
+ """Create an in-memory MLArray with evenly spaced values.
667
+
668
+ Behavior mirrors :func:`blosc2.arange` while also applying MLArray
669
+ metadata and chunk/block optimization settings.
670
+
671
+ Args:
672
+ start (Union[int, float]): Start of interval. If ``stop`` is None,
673
+ this value is treated as stop and start becomes 0.
674
+ stop (Optional[Union[int, float]]): End of interval (exclusive).
675
+ step (Optional[Union[int, float]]): Spacing between values.
676
+ dtype (np.dtype): Output dtype. If None, inferred similarly to
677
+ ``blosc2.arange``.
678
+ shape (Optional[Union[int, List, Tuple, np.ndarray]]): Target output
679
+ shape. If None, shape is inferred from start/stop/step.
680
+ c_order (bool): Store in C order (row-major) if True.
681
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
682
+ the created ``MLArray``.
683
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
684
+ chunk/block optimization. Defaults to None for this method.
685
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
686
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
687
+ num_threads (int): Number of threads for Blosc2 operations.
688
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
689
+ parameters.
690
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
691
+ decompression parameters.
692
+
693
+ Returns:
694
+ MLArray: A newly created in-memory MLArray instance.
695
+
696
+ Raises:
697
+ ValueError: If ``shape`` is inconsistent with
698
+ ``start``/``stop``/``step``.
699
+ """
700
+ if step is None:
701
+ step = 1
702
+ if stop is None:
703
+ stop = start
704
+ start = 0
705
+
706
+ num = int((stop - start) / step)
707
+ if shape is None:
708
+ shape = (max(num, 0),)
709
+ else:
710
+ shape = cls._normalize_shape(shape)
711
+ if math.prod(shape) != num:
712
+ raise ValueError(
713
+ "The shape is not consistent with the start, stop and step values"
714
+ )
715
+
716
+ if dtype is None:
717
+ dtype = (
718
+ blosc2.DEFAULT_FLOAT
719
+ if np.any([np.issubdtype(type(d), float) for d in (start, stop, step)])
720
+ else blosc2.DEFAULT_INT
721
+ )
722
+
723
+ class_instance = cls()
724
+ class_instance._construct_in_memory(
725
+ shape=shape,
726
+ dtype=dtype,
727
+ meta=meta,
728
+ patch_size=patch_size,
729
+ chunk_size=chunk_size,
730
+ block_size=block_size,
731
+ num_threads=num_threads,
732
+ cparams=cparams,
733
+ dparams=dparams,
734
+ store_builder=lambda **kwargs: blosc2.arange(
735
+ start=start,
736
+ stop=stop,
737
+ step=step,
738
+ c_order=c_order,
739
+ **kwargs,
740
+ ),
741
+ )
742
+ return class_instance
743
+
744
+ @classmethod
745
+ def linspace(
746
+ cls,
747
+ start: Union[int, float, complex],
748
+ stop: Union[int, float, complex],
749
+ num: Optional[int] = None,
750
+ dtype: np.dtype = None,
751
+ endpoint: bool = True,
752
+ shape: Optional[Union[int, List, Tuple, np.ndarray]] = None,
753
+ c_order: bool = True,
754
+ meta: Optional[Union[Dict, Meta]] = None,
755
+ patch_size: Optional[Union[int, List, Tuple]] = None,
756
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
757
+ block_size: Optional[Union[int, List, Tuple]] = None,
758
+ num_threads: int = 1,
759
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
760
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
761
+ ):
762
+ """Create an in-memory MLArray with evenly spaced samples.
763
+
764
+ Behavior mirrors :func:`blosc2.linspace` while also applying MLArray
765
+ metadata and chunk/block optimization settings.
766
+
767
+ Args:
768
+ start (Union[int, float, complex]): Start value of the sequence.
769
+ stop (Union[int, float, complex]): End value of the sequence.
770
+ num (Optional[int]): Number of samples. Required when ``shape`` is
771
+ None.
772
+ dtype (np.dtype): Output dtype. If None, inferred similarly to
773
+ ``blosc2.linspace``.
774
+ endpoint (bool): Whether ``stop`` is included.
775
+ shape (Optional[Union[int, List, Tuple, np.ndarray]]): Target output
776
+ shape. If None, inferred from ``num``.
777
+ c_order (bool): Store in C order (row-major) if True.
778
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
779
+ the created ``MLArray``.
780
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
781
+ chunk/block optimization. Defaults to None for this method.
782
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
783
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
784
+ num_threads (int): Number of threads for Blosc2 operations.
785
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
786
+ parameters.
787
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
788
+ decompression parameters.
789
+
790
+ Returns:
791
+ MLArray: A newly created in-memory MLArray instance.
792
+
793
+ Raises:
794
+ ValueError: If neither ``shape`` nor ``num`` is specified, or if the
795
+ provided ``shape`` and ``num`` are inconsistent.
796
+ """
797
+ if shape is None:
798
+ if num is None:
799
+ raise ValueError("Either `shape` or `num` must be specified.")
800
+ shape = (num,)
801
+ else:
802
+ shape = cls._normalize_shape(shape)
803
+ num = math.prod(shape) if num is None else num
804
+
805
+ if math.prod(shape) != num or num < 0:
806
+ msg = f"Shape is not consistent with the specified num value {num}."
807
+ if num < 0:
808
+ msg += "num must be nonnegative."
809
+ raise ValueError(msg)
810
+
811
+ if dtype is None:
812
+ dtype = (
813
+ blosc2.DEFAULT_COMPLEX
814
+ if np.any([np.issubdtype(type(d), complex) for d in (start, stop)])
815
+ else blosc2.DEFAULT_FLOAT
816
+ )
817
+
818
+ class_instance = cls()
819
+ class_instance._construct_in_memory(
820
+ shape=shape,
821
+ dtype=dtype,
822
+ meta=meta,
823
+ patch_size=patch_size,
824
+ chunk_size=chunk_size,
825
+ block_size=block_size,
826
+ num_threads=num_threads,
827
+ cparams=cparams,
828
+ dparams=dparams,
829
+ store_builder=lambda **kwargs: blosc2.linspace(
830
+ start=start,
831
+ stop=stop,
832
+ num=num,
833
+ endpoint=endpoint,
834
+ c_order=c_order,
835
+ **kwargs,
836
+ ),
837
+ )
838
+ return class_instance
839
+
840
+ @classmethod
841
+ def empty_like(
842
+ cls,
843
+ x,
844
+ dtype: np.dtype = None,
845
+ meta: Optional[Union[Dict, Meta]] = None,
846
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
847
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
848
+ block_size: Optional[Union[int, List, Tuple]] = None,
849
+ num_threads: int = 1,
850
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
851
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
852
+ ):
853
+ """Create an in-memory MLArray with the same shape as ``x``.
854
+
855
+ Args:
856
+ x: Source object. Can be an ``MLArray`` or any array-like object
857
+ exposing ``shape`` and ``dtype``.
858
+ dtype (np.dtype): Output dtype. If None, inferred from ``x``.
859
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
860
+ the created ``MLArray``. If ``x`` is an ``MLArray`` and ``meta``
861
+ is None, metadata is copied from ``x``.
862
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
863
+ chunk/block optimization.
864
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
865
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
866
+ num_threads (int): Number of threads for Blosc2 operations.
867
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
868
+ parameters.
869
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
870
+ decompression parameters.
871
+
872
+ Returns:
873
+ MLArray: A newly created in-memory MLArray instance.
874
+
875
+ Raises:
876
+ TypeError: If ``x`` is not an ``MLArray`` and has no ``shape``/``dtype``.
877
+ """
878
+ class_instance = cls()
879
+ shape, dtype, meta = class_instance._resolve_like_input(x, dtype, meta)
880
+ class_instance._construct_in_memory(
881
+ shape=shape,
882
+ dtype=dtype,
883
+ meta=meta,
884
+ patch_size=patch_size,
885
+ chunk_size=chunk_size,
886
+ block_size=block_size,
887
+ num_threads=num_threads,
888
+ cparams=cparams,
889
+ dparams=dparams,
890
+ store_builder=lambda **kwargs: blosc2.empty(**kwargs),
891
+ )
892
+ return class_instance
893
+
894
+ @classmethod
895
+ def zeros_like(
896
+ cls,
897
+ x,
898
+ dtype: np.dtype = None,
899
+ meta: Optional[Union[Dict, Meta]] = None,
900
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
901
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
902
+ block_size: Optional[Union[int, List, Tuple]] = None,
903
+ num_threads: int = 1,
904
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
905
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
906
+ ):
907
+ """Create an in-memory MLArray of zeros with the same shape as ``x``.
908
+
909
+ Args:
910
+ x: Source object. Can be an ``MLArray`` or any array-like object
911
+ exposing ``shape`` and ``dtype``.
912
+ dtype (np.dtype): Output dtype. If None, inferred from ``x``.
913
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
914
+ the created ``MLArray``. If ``x`` is an ``MLArray`` and ``meta``
915
+ is None, metadata is copied from ``x``.
916
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
917
+ chunk/block optimization.
918
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
919
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
920
+ num_threads (int): Number of threads for Blosc2 operations.
921
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
922
+ parameters.
923
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
924
+ decompression parameters.
925
+
926
+ Returns:
927
+ MLArray: A newly created in-memory MLArray instance.
928
+
929
+ Raises:
930
+ TypeError: If ``x`` is not an ``MLArray`` and has no ``shape``/``dtype``.
931
+ """
932
+ class_instance = cls()
933
+ shape, dtype, meta = class_instance._resolve_like_input(x, dtype, meta)
934
+ class_instance._construct_in_memory(
935
+ shape=shape,
936
+ dtype=dtype,
937
+ meta=meta,
938
+ patch_size=patch_size,
939
+ chunk_size=chunk_size,
940
+ block_size=block_size,
941
+ num_threads=num_threads,
942
+ cparams=cparams,
943
+ dparams=dparams,
944
+ store_builder=lambda **kwargs: blosc2.zeros(**kwargs),
945
+ )
946
+ return class_instance
947
+
948
+ @classmethod
949
+ def ones_like(
950
+ cls,
951
+ x,
952
+ dtype: np.dtype = None,
953
+ meta: Optional[Union[Dict, Meta]] = None,
954
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
955
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
956
+ block_size: Optional[Union[int, List, Tuple]] = None,
957
+ num_threads: int = 1,
958
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
959
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
960
+ ):
961
+ """Create an in-memory MLArray of ones with the same shape as ``x``.
962
+
963
+ Args:
964
+ x: Source object. Can be an ``MLArray`` or any array-like object
965
+ exposing ``shape`` and ``dtype``.
966
+ dtype (np.dtype): Output dtype. If None, inferred from ``x``.
967
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
968
+ the created ``MLArray``. If ``x`` is an ``MLArray`` and ``meta``
969
+ is None, metadata is copied from ``x``.
970
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
971
+ chunk/block optimization.
972
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
973
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
974
+ num_threads (int): Number of threads for Blosc2 operations.
975
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
976
+ parameters.
977
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
978
+ decompression parameters.
979
+
980
+ Returns:
981
+ MLArray: A newly created in-memory MLArray instance.
982
+
983
+ Raises:
984
+ TypeError: If ``x`` is not an ``MLArray`` and has no ``shape``/``dtype``.
985
+ """
986
+ class_instance = cls()
987
+ shape, dtype, meta = class_instance._resolve_like_input(x, dtype, meta)
988
+ class_instance._construct_in_memory(
989
+ shape=shape,
990
+ dtype=dtype,
991
+ meta=meta,
992
+ patch_size=patch_size,
993
+ chunk_size=chunk_size,
994
+ block_size=block_size,
995
+ num_threads=num_threads,
996
+ cparams=cparams,
997
+ dparams=dparams,
998
+ store_builder=lambda **kwargs: blosc2.ones(**kwargs),
999
+ )
1000
+ return class_instance
1001
+
1002
+ @classmethod
1003
+ def full_like(
1004
+ cls,
1005
+ x,
1006
+ fill_value: Union[bool, int, float, complex],
1007
+ dtype: np.dtype = None,
1008
+ meta: Optional[Union[Dict, Meta]] = None,
1009
+ patch_size: Optional[Union[int, List, Tuple]] = "default",
1010
+ chunk_size: Optional[Union[int, List, Tuple]] = None,
1011
+ block_size: Optional[Union[int, List, Tuple]] = None,
1012
+ num_threads: int = 1,
1013
+ cparams: Optional[Union[Dict, blosc2.CParams]] = None,
1014
+ dparams: Optional[Union[Dict, blosc2.DParams]] = None,
1015
+ ):
1016
+ """Create an in-memory MLArray filled with ``fill_value`` and shape of ``x``.
1017
+
1018
+ Args:
1019
+ x: Source object. Can be an ``MLArray`` or any array-like object
1020
+ exposing ``shape`` and ``dtype``.
1021
+ fill_value (Union[bool, int, float, complex]): Fill value used for
1022
+ all elements in the output.
1023
+ dtype (np.dtype): Output dtype. If None, inferred from ``x``.
1024
+ meta (Optional[Union[Dict, Meta]]): Optional metadata attached to
1025
+ the created ``MLArray``. If ``x`` is an ``MLArray`` and ``meta``
1026
+ is None, metadata is copied from ``x``.
1027
+ patch_size (Optional[Union[int, List, Tuple]]): Patch size hint for
1028
+ chunk/block optimization.
1029
+ chunk_size (Optional[Union[int, List, Tuple]]): Explicit chunk size.
1030
+ block_size (Optional[Union[int, List, Tuple]]): Explicit block size.
1031
+ num_threads (int): Number of threads for Blosc2 operations.
1032
+ cparams (Optional[Union[Dict, blosc2.CParams]]): Blosc2 compression
1033
+ parameters.
1034
+ dparams (Optional[Union[Dict, blosc2.DParams]]): Blosc2
1035
+ decompression parameters.
1036
+
1037
+ Returns:
1038
+ MLArray: A newly created in-memory MLArray instance.
1039
+
1040
+ Raises:
1041
+ TypeError: If ``x`` is not an ``MLArray`` and has no ``shape``/``dtype``.
1042
+ """
1043
+ class_instance = cls()
1044
+ shape, dtype, meta = class_instance._resolve_like_input(x, dtype, meta)
1045
+ class_instance._construct_in_memory(
1046
+ shape=shape,
1047
+ dtype=dtype,
1048
+ meta=meta,
1049
+ patch_size=patch_size,
1050
+ chunk_size=chunk_size,
1051
+ block_size=block_size,
1052
+ num_threads=num_threads,
1053
+ cparams=cparams,
1054
+ dparams=dparams,
1055
+ store_builder=lambda **kwargs: blosc2.full(fill_value=fill_value, **kwargs),
1056
+ )
1057
+ return class_instance
1058
+
331
1059
  def close(self):
332
1060
  """Flush metadata and close the underlying store.
333
1061
 
@@ -1010,12 +1738,19 @@ class MLArray:
1010
1738
  raise NotImplementedError("Chunk and block size optimization based on patch size is only implemented for 2D and 3D spatial images with at most one further non-spatial axis. Please set the chunk and block size manually or set to None for blosc2 to determine a chunk and block size.")
1011
1739
  if patch_size is not None and patch_size != "default" and (chunk_size is not None or block_size is not None):
1012
1740
  raise RuntimeError("patch_size and chunk_size / block_size cannot both be explicitly set.")
1741
+ if (chunk_size is not None and block_size is None) or (chunk_size is None and block_size is not None):
1742
+ raise RuntimeError("If either chunk/block size is used then both must be set.")
1013
1743
 
1014
1744
  if patch_size == "default":
1015
1745
  if meta_blosc2 is not None and meta_blosc2.patch_size is not None: # Use previously loaded patch size, when patch size is not explicitly set and a patch size from a previously loaded image exists
1016
1746
  patch_size = meta_blosc2.patch_size
1747
+ elif meta_blosc2 is not None and (meta_blosc2.chunk_size is not None):
1748
+ chunk_size = meta_blosc2.chunk_size
1749
+ block_size = meta_blosc2.block_size
1017
1750
  else: # Use default patch size, when patch size is not explicitly set and no patch size from a previously loaded image exists
1018
1751
  patch_size = [MLARRAY_DEFAULT_PATCH_SIZE] * num_spatial_axes
1752
+ if chunk_size is not None or block_size is not None:
1753
+ patch_size = None
1019
1754
 
1020
1755
  patch_size = [patch_size] * len(shape) if isinstance(patch_size, int) else patch_size
1021
1756
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlarray
3
- Version: 0.0.43
3
+ Version: 0.0.45
4
4
  Summary: Array format specialized for Machine Learning with Blosc2 backend and standardized metadata.
5
5
  Author-email: Karol Gotkowski <karol.gotkowski@dkfz.de>
6
6
  License: MIT
@@ -22,6 +22,7 @@ docs/why.md
22
22
  examples/example_asarray.py
23
23
  examples/example_bboxes_only.py
24
24
  examples/example_channel.py
25
+ examples/example_in_memory_constructors.py
25
26
  examples/example_metadata_only.py
26
27
  examples/example_non_spatial.py
27
28
  examples/example_open.py
@@ -39,6 +40,7 @@ mlarray.egg-info/requires.txt
39
40
  mlarray.egg-info/top_level.txt
40
41
  tests/test_asarray.py
41
42
  tests/test_bboxes.py
43
+ tests/test_constructors.py
42
44
  tests/test_create.py
43
45
  tests/test_metadata.py
44
46
  tests/test_open.py
@@ -0,0 +1,135 @@
1
+ import tempfile
2
+ import unittest
3
+ from pathlib import Path
4
+
5
+ import blosc2
6
+ import numpy as np
7
+
8
+ from mlarray import MLArray
9
+
10
+
11
+ class TestInMemoryConstructors(unittest.TestCase):
12
+ def test_empty_and_save_roundtrip(self):
13
+ shape = (4, 8, 8)
14
+ arr = MLArray.empty(
15
+ shape=shape,
16
+ dtype=np.float32,
17
+ patch_size=None,
18
+ chunk_size=(1, 4, 4),
19
+ block_size=(1, 2, 2),
20
+ num_threads=1,
21
+ cparams={"codec": blosc2.Codec.LZ4HC, "clevel": 1},
22
+ dparams={"nthreads": 1},
23
+ )
24
+
25
+ data = np.arange(np.prod(shape), dtype=np.float32).reshape(shape)
26
+ arr[...] = data
27
+
28
+ with tempfile.TemporaryDirectory() as tmpdir:
29
+ path = Path(tmpdir) / "in-memory-empty.mla"
30
+ arr.save(path)
31
+ loaded = MLArray(path)
32
+
33
+ self.assertEqual(loaded.shape, shape)
34
+ self.assertTrue(np.allclose(loaded[...], data))
35
+
36
+ def test_zeros_ones_full(self):
37
+ shape = (3, 5)
38
+
39
+ zeros = MLArray.zeros(
40
+ shape=shape,
41
+ dtype=np.int32,
42
+ patch_size=None,
43
+ chunk_size=(3, 5),
44
+ block_size=(1, 5),
45
+ )
46
+ ones = MLArray.ones(
47
+ shape=shape,
48
+ dtype=np.float32,
49
+ patch_size=None,
50
+ chunk_size=(3, 5),
51
+ block_size=(1, 5),
52
+ )
53
+ full = MLArray.full(
54
+ shape=shape,
55
+ fill_value=7,
56
+ dtype=np.int16,
57
+ patch_size=None,
58
+ chunk_size=(3, 5),
59
+ block_size=(1, 5),
60
+ )
61
+
62
+ self.assertTrue(np.array_equal(zeros[...], np.zeros(shape, dtype=np.int32)))
63
+ self.assertTrue(np.array_equal(ones[...], np.ones(shape, dtype=np.float32)))
64
+ self.assertTrue(np.array_equal(full[...], np.full(shape, 7, dtype=np.int16)))
65
+
66
+ def test_arange_and_linspace(self):
67
+ arr1 = MLArray.arange(0, 12, 2, patch_size=None, num_threads=1)
68
+ self.assertTrue(np.array_equal(arr1[...], np.arange(0, 12, 2)))
69
+
70
+ arr2 = MLArray.arange(0, 12, 2, shape=(2, 3), patch_size=None, num_threads=1)
71
+ self.assertTrue(np.array_equal(arr2[...], np.arange(0, 12, 2).reshape(2, 3)))
72
+
73
+ lin = MLArray.linspace(
74
+ 0.0, 1.0, num=6, shape=(2, 3), endpoint=False, patch_size=None, num_threads=1
75
+ )
76
+ self.assertTrue(
77
+ np.allclose(lin[...], np.linspace(0.0, 1.0, 6, endpoint=False).reshape(2, 3))
78
+ )
79
+
80
+ def test_like_methods_and_meta_copy(self):
81
+ base = MLArray.full(
82
+ shape=(2, 3, 4),
83
+ fill_value=5,
84
+ dtype=np.int16,
85
+ meta={"case": "meta-copy"},
86
+ patch_size=None,
87
+ chunk_size=(1, 3, 4),
88
+ block_size=(1, 2, 2),
89
+ )
90
+
91
+ empty_like = MLArray.empty_like(
92
+ base, patch_size=None, chunk_size=(1, 3, 4), block_size=(1, 2, 2)
93
+ )
94
+ zeros_like = MLArray.zeros_like(
95
+ base, patch_size=None, chunk_size=(1, 3, 4), block_size=(1, 2, 2)
96
+ )
97
+ ones_like = MLArray.ones_like(
98
+ base,
99
+ dtype=np.float32,
100
+ patch_size=None,
101
+ chunk_size=(1, 3, 4),
102
+ block_size=(1, 2, 2),
103
+ )
104
+ full_like = MLArray.full_like(
105
+ base,
106
+ fill_value=9,
107
+ patch_size=None,
108
+ chunk_size=(1, 3, 4),
109
+ block_size=(1, 2, 2),
110
+ )
111
+
112
+ self.assertEqual(empty_like.shape, base.shape)
113
+ self.assertEqual(zeros_like.shape, base.shape)
114
+ self.assertEqual(ones_like.shape, base.shape)
115
+ self.assertEqual(full_like.shape, base.shape)
116
+
117
+ self.assertTrue(
118
+ np.array_equal(zeros_like[...], np.zeros(base.shape, dtype=base.dtype))
119
+ )
120
+ self.assertTrue(
121
+ np.array_equal(ones_like[...], np.ones(base.shape, dtype=np.float32))
122
+ )
123
+ self.assertTrue(
124
+ np.array_equal(full_like[...], np.full(base.shape, 9, dtype=base.dtype))
125
+ )
126
+
127
+ self.assertEqual(zeros_like.meta.source.to_plain(), {"case": "meta-copy"})
128
+
129
+ def test_like_raises_for_invalid_input(self):
130
+ with self.assertRaises(TypeError):
131
+ MLArray.zeros_like(123)
132
+
133
+
134
+ if __name__ == "__main__":
135
+ unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes