ngio 0.2.0a2__py3-none-any.whl → 0.5.0b4__py3-none-any.whl

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 (106) hide show
  1. ngio/__init__.py +40 -12
  2. ngio/common/__init__.py +16 -32
  3. ngio/common/_dimensions.py +270 -48
  4. ngio/common/_masking_roi.py +153 -0
  5. ngio/common/_pyramid.py +267 -73
  6. ngio/common/_roi.py +290 -66
  7. ngio/common/_synt_images_utils.py +101 -0
  8. ngio/common/_zoom.py +54 -22
  9. ngio/experimental/__init__.py +5 -0
  10. ngio/experimental/iterators/__init__.py +15 -0
  11. ngio/experimental/iterators/_abstract_iterator.py +390 -0
  12. ngio/experimental/iterators/_feature.py +189 -0
  13. ngio/experimental/iterators/_image_processing.py +130 -0
  14. ngio/experimental/iterators/_mappers.py +48 -0
  15. ngio/experimental/iterators/_rois_utils.py +126 -0
  16. ngio/experimental/iterators/_segmentation.py +235 -0
  17. ngio/hcs/__init__.py +17 -58
  18. ngio/hcs/_plate.py +1354 -0
  19. ngio/images/__init__.py +30 -9
  20. ngio/images/_abstract_image.py +968 -0
  21. ngio/images/_create_synt_container.py +132 -0
  22. ngio/images/_create_utils.py +423 -0
  23. ngio/images/_image.py +926 -0
  24. ngio/images/_label.py +417 -0
  25. ngio/images/_masked_image.py +531 -0
  26. ngio/images/_ome_zarr_container.py +1235 -0
  27. ngio/images/_table_ops.py +471 -0
  28. ngio/io_pipes/__init__.py +75 -0
  29. ngio/io_pipes/_io_pipes.py +361 -0
  30. ngio/io_pipes/_io_pipes_masked.py +488 -0
  31. ngio/io_pipes/_io_pipes_roi.py +146 -0
  32. ngio/io_pipes/_io_pipes_types.py +56 -0
  33. ngio/io_pipes/_match_shape.py +377 -0
  34. ngio/io_pipes/_ops_axes.py +344 -0
  35. ngio/io_pipes/_ops_slices.py +411 -0
  36. ngio/io_pipes/_ops_slices_utils.py +199 -0
  37. ngio/io_pipes/_ops_transforms.py +104 -0
  38. ngio/io_pipes/_zoom_transform.py +180 -0
  39. ngio/ome_zarr_meta/__init__.py +39 -15
  40. ngio/ome_zarr_meta/_meta_handlers.py +490 -96
  41. ngio/ome_zarr_meta/ngio_specs/__init__.py +24 -10
  42. ngio/ome_zarr_meta/ngio_specs/_axes.py +268 -234
  43. ngio/ome_zarr_meta/ngio_specs/_channels.py +125 -41
  44. ngio/ome_zarr_meta/ngio_specs/_dataset.py +42 -87
  45. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +536 -2
  46. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +202 -198
  47. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +72 -34
  48. ngio/ome_zarr_meta/v04/__init__.py +21 -5
  49. ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
  50. ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +151 -90
  51. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  52. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  53. ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
  54. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  55. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  56. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  57. ngio/resources/__init__.py +55 -0
  58. ngio/resources/resource_model.py +36 -0
  59. ngio/tables/__init__.py +20 -4
  60. ngio/tables/_abstract_table.py +270 -0
  61. ngio/tables/_tables_container.py +449 -0
  62. ngio/tables/backends/__init__.py +50 -1
  63. ngio/tables/backends/_abstract_backend.py +200 -31
  64. ngio/tables/backends/_anndata.py +139 -0
  65. ngio/tables/backends/_anndata_utils.py +10 -114
  66. ngio/tables/backends/_csv.py +19 -0
  67. ngio/tables/backends/_json.py +92 -0
  68. ngio/tables/backends/_parquet.py +19 -0
  69. ngio/tables/backends/_py_arrow_backends.py +222 -0
  70. ngio/tables/backends/_table_backends.py +162 -38
  71. ngio/tables/backends/_utils.py +608 -0
  72. ngio/tables/v1/__init__.py +19 -4
  73. ngio/tables/v1/_condition_table.py +71 -0
  74. ngio/tables/v1/_feature_table.py +79 -115
  75. ngio/tables/v1/_generic_table.py +21 -90
  76. ngio/tables/v1/_roi_table.py +486 -137
  77. ngio/transforms/__init__.py +5 -0
  78. ngio/transforms/_zoom.py +19 -0
  79. ngio/utils/__init__.py +16 -14
  80. ngio/utils/_cache.py +48 -0
  81. ngio/utils/_datasets.py +121 -13
  82. ngio/utils/_fractal_fsspec_store.py +42 -0
  83. ngio/utils/_zarr_utils.py +374 -218
  84. ngio-0.5.0b4.dist-info/METADATA +147 -0
  85. ngio-0.5.0b4.dist-info/RECORD +88 -0
  86. {ngio-0.2.0a2.dist-info → ngio-0.5.0b4.dist-info}/WHEEL +1 -1
  87. ngio/common/_array_pipe.py +0 -160
  88. ngio/common/_axes_transforms.py +0 -63
  89. ngio/common/_common_types.py +0 -5
  90. ngio/common/_slicer.py +0 -97
  91. ngio/images/abstract_image.py +0 -240
  92. ngio/images/create.py +0 -251
  93. ngio/images/image.py +0 -389
  94. ngio/images/label.py +0 -236
  95. ngio/images/omezarr_container.py +0 -535
  96. ngio/ome_zarr_meta/_generic_handlers.py +0 -320
  97. ngio/ome_zarr_meta/v04/_meta_handlers.py +0 -54
  98. ngio/tables/_validators.py +0 -192
  99. ngio/tables/backends/_anndata_v1.py +0 -75
  100. ngio/tables/backends/_json_v1.py +0 -56
  101. ngio/tables/tables_container.py +0 -300
  102. ngio/tables/v1/_masking_roi_table.py +0 -175
  103. ngio/utils/_logger.py +0 -29
  104. ngio-0.2.0a2.dist-info/METADATA +0 -95
  105. ngio-0.2.0a2.dist-info/RECORD +0 -53
  106. {ngio-0.2.0a2.dist-info → ngio-0.5.0b4.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,539 @@
1
1
  """HCS (High Content Screening) specific metadata classes for NGIO."""
2
2
 
3
+ import warnings
4
+ from typing import Annotated
3
5
 
4
- class NgioWellMeta:
5
- images: list[str]
6
+ from ome_zarr_models.common.plate import (
7
+ Acquisition,
8
+ Column,
9
+ PlateBase,
10
+ Row,
11
+ WellInPlate,
12
+ )
13
+ from ome_zarr_models.common.well_types import WellImage as WellImageCommon
14
+ from pydantic import BaseModel, SkipValidation, field_serializer
15
+
16
+ from ngio.ome_zarr_meta.ngio_specs._ngio_image import DefaultNgffVersion, NgffVersions
17
+ from ngio.utils import NgioValueError
18
+
19
+
20
+ def path_in_well_validation(path: str) -> str:
21
+ """Validate the path in the well."""
22
+ # Check if the value contains only alphanumeric characters
23
+ if not path.isalnum():
24
+ warnings.warn(
25
+ f"Path '{path}' contains non-alphanumeric characters. "
26
+ "This may cause issues with some tools. "
27
+ "Consider using only alphanumeric characters in the path.",
28
+ stacklevel=2,
29
+ )
30
+ return path
31
+
32
+
33
+ class ImageInWellPath(BaseModel):
34
+ """Image in a well."""
35
+
36
+ row: str
37
+ column: str | int
38
+ path: str
39
+ acquisition_id: int | None = None
40
+ acquisition_name: str | None = None
41
+
42
+
43
+ class CustomWellImage(WellImageCommon):
44
+ path: Annotated[str, SkipValidation]
45
+
46
+ @field_serializer("path")
47
+ def serialize_path(self, value: str) -> str:
48
+ """Custom serialization for the path."""
49
+ return path_in_well_validation(value)
50
+
51
+
52
+ class PlateWithVersion(PlateBase):
53
+ version: NgffVersions
54
+
55
+
56
+ class NgioWellMeta(BaseModel):
57
+ """HCS well metadata."""
58
+
59
+ images: list[CustomWellImage] # type: ignore (override of WellMeta04.images)
60
+ version: NgffVersions
61
+
62
+ @classmethod
63
+ def default_init(
64
+ cls,
65
+ ngff_version: NgffVersions = DefaultNgffVersion,
66
+ ) -> "NgioWellMeta":
67
+ well = cls(images=[], version=ngff_version)
68
+ return well
69
+
70
+ @property
71
+ def acquisition_ids(self) -> list[int]:
72
+ """Return the acquisition ids in the well."""
73
+ acquisitions = []
74
+ for images in self.images:
75
+ if (
76
+ images.acquisition is not None
77
+ and images.acquisition not in acquisitions
78
+ ):
79
+ acquisitions.append(images.acquisition)
80
+ return acquisitions
81
+
82
+ def get_image_acquisition_id(self, image_path: str) -> int | None:
83
+ """Return the acquisition id for the given image path."""
84
+ for images in self.images:
85
+ if images.path == image_path:
86
+ return images.acquisition
87
+ raise NgioValueError(f"Image at path {image_path} not found in the well.")
88
+
89
+ def paths(self, acquisition: int | None = None) -> list[str]:
90
+ """Return the images paths in the well.
91
+
92
+ If acquisition is None, return all images paths in the well.
93
+ Else, return the images paths in the well for the given acquisition.
94
+
95
+ Args:
96
+ acquisition (int | None): The acquisition id to filter the images.
97
+ """
98
+ if acquisition is None:
99
+ return [images.path for images in self.images]
100
+ return [
101
+ images.path for images in self.images if images.acquisition == acquisition
102
+ ]
103
+
104
+ def add_image(
105
+ self, path: str, acquisition: int | None = None, strict: bool = True
106
+ ) -> "NgioWellMeta":
107
+ """Add an image to the well.
108
+
109
+ Args:
110
+ path (str): The path of the image.
111
+ acquisition (int | None): The acquisition id of the image.
112
+ strict (bool): If True, check if the image already exists in the well.
113
+ If False, do not check if the image already exists in the well.
114
+ """
115
+ list_of_images = self.images
116
+ for image in list_of_images:
117
+ if image.path == path:
118
+ raise NgioValueError(
119
+ f"Image at path {path} already exists in the well."
120
+ )
121
+
122
+ if (
123
+ strict
124
+ and (acquisition is not None)
125
+ and (acquisition not in self.acquisition_ids)
126
+ ):
127
+ raise NgioValueError(
128
+ f"Acquisition ID {acquisition} not found in well. "
129
+ "Please add it to the plate metadata first."
130
+ )
131
+
132
+ new_image = CustomWellImage(path=path, acquisition=acquisition)
133
+ list_of_images.append(new_image)
134
+ return NgioWellMeta(images=list_of_images, version=self.version)
135
+
136
+ def remove_image(self, path: str) -> "NgioWellMeta":
137
+ """Remove an image from the well.
138
+
139
+ Args:
140
+ path (str): The path of the image.
141
+ """
142
+ list_of_images = self.images
143
+ for image in list_of_images:
144
+ if image.path == path:
145
+ list_of_images.remove(image)
146
+ return NgioWellMeta(images=list_of_images, version=self.version)
147
+ raise NgioValueError(f"Image at path {path} not found in the well.")
148
+
149
+
150
+ def _stringify_column(column: str | int) -> str:
151
+ """Convert the column to a string.
152
+
153
+ Args:
154
+ column (str | int): The column to convert.
155
+
156
+ Returns:
157
+ str: The column as a string.
158
+ """
159
+ if isinstance(column, str):
160
+ return column
161
+
162
+ # Maybe we should pad the column with zeros
163
+ return str(column)
164
+
165
+
166
+ def _find_row_index(rows: list[str], row: str) -> int | None:
167
+ try:
168
+ return rows.index(row)
169
+ except ValueError:
170
+ return None
171
+
172
+
173
+ def _find_column_index(columns: list[str], column: str | int) -> int | None:
174
+ _num_columns = [int(columns) for columns in columns]
175
+ column = int(column)
176
+ try:
177
+ return _num_columns.index(column)
178
+ except ValueError:
179
+ return None
180
+
181
+
182
+ def _relabel_wells(
183
+ wells: list[WellInPlate], rows: list[Row], columns: list[Column]
184
+ ) -> list[WellInPlate]:
185
+ new_wells = []
186
+ _rows = [row.name for row in rows]
187
+ _columns = [column.name for column in columns]
188
+ for well in wells:
189
+ row, column = well.path.split("/")
190
+ row_idx = _find_row_index(_rows, row)
191
+ column_idx = _find_column_index(_columns, column)
192
+
193
+ if row_idx is None:
194
+ raise NgioValueError(f"Row {row} not found in the plate.")
195
+ if column_idx is None:
196
+ raise NgioValueError(f"Column {column} not found in the plate.")
197
+
198
+ new_wells.append(
199
+ WellInPlate(
200
+ path=well.path,
201
+ rowIndex=row_idx,
202
+ columnIndex=column_idx,
203
+ )
204
+ )
205
+
206
+ return new_wells
207
+
208
+
209
+ class NgioPlateMeta(BaseModel):
210
+ """HCS plate metadata."""
211
+
212
+ plate: PlateWithVersion
213
+ version: NgffVersions
214
+
215
+ @classmethod
216
+ def default_init(
217
+ cls,
218
+ images: list[ImageInWellPath] | None = None,
219
+ name: str | None = None,
220
+ ngff_version: NgffVersions = DefaultNgffVersion,
221
+ ) -> "NgioPlateMeta":
222
+ plate = cls(
223
+ plate=PlateWithVersion(
224
+ rows=[],
225
+ columns=[],
226
+ acquisitions=None,
227
+ wells=[],
228
+ field_count=None,
229
+ name=name,
230
+ version=ngff_version,
231
+ ),
232
+ version=ngff_version,
233
+ )
234
+
235
+ if images is None:
236
+ return plate
237
+
238
+ for image in images:
239
+ plate = plate.add_well(
240
+ row=image.row,
241
+ column=image.column,
242
+ )
243
+ if image.acquisition_id is not None:
244
+ plate = plate.add_acquisition(
245
+ acquisition_id=image.acquisition_id,
246
+ acquisition_name=image.acquisition_name,
247
+ )
248
+ return plate
249
+
250
+ @property
251
+ def columns(self) -> list[str]:
252
+ """Returns the list of columns in the plate."""
253
+ return [columns.name for columns in self.plate.columns]
254
+
255
+ @property
256
+ def rows(self) -> list[str]:
257
+ """Returns the list of rows in the plate."""
258
+ return [rows.name for rows in self.plate.rows]
259
+
260
+ @property
261
+ def acquisitions_names(self) -> list[str | None]:
262
+ """Return the acquisitions in the plate."""
263
+ if self.plate.acquisitions is None:
264
+ return []
265
+ return [acquisitions.name for acquisitions in self.plate.acquisitions]
266
+
267
+ @property
268
+ def acquisition_ids(self) -> list[int]:
269
+ """Return the acquisitions ids in the plate."""
270
+ if self.plate.acquisitions is None:
271
+ return []
272
+ return [acquisitions.id for acquisitions in self.plate.acquisitions]
273
+
274
+ @property
275
+ def wells_paths(self) -> list[str]:
276
+ """Return the wells paths in the plate."""
277
+ return [wells.path for wells in self.plate.wells]
278
+
279
+ def get_well_path(self, row: str, column: str | int) -> str:
280
+ """Return the well path for the given row and column.
281
+
282
+ Args:
283
+ row (str): The row of the well.
284
+ column (str | int): The column of the well.
285
+
286
+ Returns:
287
+ str: The path of the well.
288
+ """
289
+ if row not in self.rows:
290
+ raise NgioValueError(
291
+ f"Row {row} not found in the plate. Available rows are {self.rows}."
292
+ )
293
+
294
+ row_idx = self.rows.index(row)
295
+
296
+ _num_columns = [int(columns) for columns in self.columns]
297
+
298
+ try:
299
+ _column = int(column)
300
+ except ValueError:
301
+ raise NgioValueError(
302
+ f"Column {column} must be an integer or convertible to an integer."
303
+ ) from None
304
+
305
+ column_idx = _num_columns.index(_column)
306
+
307
+ for well in self.plate.wells:
308
+ if well.columnIndex == column_idx and well.rowIndex == row_idx:
309
+ return well.path
310
+
311
+ raise NgioValueError(
312
+ f"Well at row {row} and column {column} not found in the plate."
313
+ )
314
+
315
+ def add_row(self, row: str) -> "tuple[NgioPlateMeta, int]":
316
+ """Add a row to the plate.
317
+
318
+ Args:
319
+ row (str): The row to add.
320
+ """
321
+ relabel_wells = False
322
+
323
+ row_names = self.rows
324
+ row_idx = _find_row_index(row_names, row)
325
+ if row_idx is not None:
326
+ # Nothing to do
327
+ return self, row_idx
328
+
329
+ row_names.append(row)
330
+ row_names.sort()
331
+ row_idx = row_names.index(row)
332
+ relabel_wells = True
333
+
334
+ rows = [Row(name=row) for row in row_names]
335
+
336
+ if relabel_wells:
337
+ wells = _relabel_wells(self.plate.wells, rows, self.plate.columns)
338
+ else:
339
+ wells = self.plate.wells
340
+
341
+ new_plate = PlateWithVersion(
342
+ rows=rows,
343
+ columns=self.plate.columns,
344
+ acquisitions=self.plate.acquisitions,
345
+ wells=wells,
346
+ field_count=self.plate.field_count,
347
+ name=self.plate.name,
348
+ version=self.version,
349
+ )
350
+ return NgioPlateMeta(plate=new_plate, version=self.version), row_idx
351
+
352
+ def add_column(self, column: str | int) -> "tuple[NgioPlateMeta, int]":
353
+ """Add a column to the plate.
354
+
355
+ Args:
356
+ column (str | int): The column to add.
357
+ """
358
+ relabel_wells = False
359
+
360
+ columns_names = self.columns
361
+ column_idx = _find_column_index(columns_names, column)
362
+ if column_idx is not None:
363
+ # Nothing to do
364
+ return self, column_idx
365
+
366
+ columns_names.append(_stringify_column(column))
367
+ # sort as numbers
368
+ columns_names.sort(key=lambda x: int(x))
369
+ column_idx = columns_names.index(_stringify_column(column))
370
+ relabel_wells = True
371
+
372
+ columns = [Column(name=column) for column in columns_names]
373
+
374
+ if relabel_wells:
375
+ wells = _relabel_wells(self.plate.wells, self.plate.rows, columns)
376
+ else:
377
+ wells = self.plate.wells
378
+
379
+ new_plate = PlateWithVersion(
380
+ rows=self.plate.rows,
381
+ columns=columns,
382
+ acquisitions=self.plate.acquisitions,
383
+ wells=wells,
384
+ field_count=self.plate.field_count,
385
+ name=self.plate.name,
386
+ version=self.version,
387
+ )
388
+ return NgioPlateMeta(plate=new_plate, version=self.version), column_idx
389
+
390
+ def add_well(
391
+ self,
392
+ row: str,
393
+ column: str | int,
394
+ ) -> "NgioPlateMeta":
395
+ """Add an image to the well.
396
+
397
+ Args:
398
+ row (str): The row of the well.
399
+ column (str | int): The column of the well.
400
+ """
401
+ plate, row_idx = self.add_row(row=row)
402
+ plate, column_idx = plate.add_column(column=column)
403
+
404
+ wells = plate.plate.wells
405
+ for well_obj in wells:
406
+ if well_obj.rowIndex == row_idx and well_obj.columnIndex == column_idx:
407
+ break
408
+ else:
409
+ wells.append(
410
+ WellInPlate(
411
+ path=f"{row}/{_stringify_column(column)}",
412
+ rowIndex=row_idx,
413
+ columnIndex=column_idx,
414
+ )
415
+ )
416
+
417
+ new_plate = PlateWithVersion(
418
+ rows=plate.plate.rows,
419
+ columns=plate.plate.columns,
420
+ acquisitions=plate.plate.acquisitions,
421
+ wells=wells,
422
+ field_count=plate.plate.field_count,
423
+ name=plate.plate.name,
424
+ version=plate.version,
425
+ )
426
+ return NgioPlateMeta(plate=new_plate, version=plate.version)
427
+
428
+ def add_acquisition(
429
+ self,
430
+ acquisition_id: int,
431
+ acquisition_name: str | None = None,
432
+ **acquisition_kwargs,
433
+ ) -> "NgioPlateMeta":
434
+ """Add an acquisition to the plate.
435
+
436
+ Args:
437
+ acquisition_id (int): The acquisition id of the well.
438
+ acquisition_name (str | None): The acquisition name of the well.
439
+ **acquisition_kwargs: Additional acquisition metadata.
440
+ """
441
+ acquisitions = self.plate.acquisitions
442
+ if acquisitions is None:
443
+ acquisitions = []
444
+
445
+ for acquisition_obj in acquisitions:
446
+ if acquisition_obj.id == acquisition_id:
447
+ # If the acquisition already exists
448
+ # Nothing to do
449
+ # Maybe we should update the acquisition name and kwargs
450
+ return self
451
+
452
+ acquisitions.append(
453
+ Acquisition(id=acquisition_id, name=acquisition_name, **acquisition_kwargs)
454
+ )
455
+
456
+ new_plate = PlateWithVersion(
457
+ rows=self.plate.rows,
458
+ columns=self.plate.columns,
459
+ acquisitions=acquisitions,
460
+ wells=self.plate.wells,
461
+ field_count=self.plate.field_count,
462
+ name=self.plate.name,
463
+ version=self.version,
464
+ )
465
+ return NgioPlateMeta(plate=new_plate, version=self.version)
466
+
467
+ def remove_well(self, row: str, column: str | int) -> "NgioPlateMeta":
468
+ """Remove a well from the plate.
469
+
470
+ Args:
471
+ row (str): The row of the well.
472
+ column (str | int): The column of the well.
473
+ """
474
+ row_idx = _find_row_index(self.rows, row)
475
+ if row_idx is None:
476
+ raise NgioValueError(f"Row {row} not found in the plate.")
477
+
478
+ column_idx = _find_column_index(self.columns, column)
479
+ if column_idx is None:
480
+ raise NgioValueError(f"Column {column} not found in the plate.")
481
+
482
+ wells = self.plate.wells
483
+ for well_obj in wells:
484
+ if well_obj.rowIndex == row_idx and well_obj.columnIndex == column_idx:
485
+ wells.remove(well_obj)
486
+ break
487
+ else:
488
+ raise NgioValueError(
489
+ f"Well at row {row} and column {column} not found in the plate."
490
+ )
491
+
492
+ new_plate = PlateWithVersion(
493
+ rows=self.plate.rows,
494
+ columns=self.plate.columns,
495
+ acquisitions=self.plate.acquisitions,
496
+ wells=wells,
497
+ field_count=self.plate.field_count,
498
+ name=self.plate.name,
499
+ version=self.version,
500
+ )
501
+ return NgioPlateMeta(plate=new_plate, version=self.version)
502
+
503
+ def derive(
504
+ self,
505
+ name: str | None = None,
506
+ ngff_version: NgffVersions | None = None,
507
+ keep_acquisitions: bool = False,
508
+ ) -> "NgioPlateMeta":
509
+ """Derive the plate metadata.
510
+
511
+ Args:
512
+ name (str): The name of the derived plate.
513
+ ngff_version (NgffVersion | None): The version of the derived plate.
514
+ If None, use the version of the original plate.
515
+ keep_acquisitions (bool): If True, keep the acquisitions in the plate.
516
+ """
517
+ columns = self.plate.columns
518
+ rows = self.plate.rows
519
+
520
+ if keep_acquisitions:
521
+ acquisitions = self.plate.acquisitions
522
+ else:
523
+ acquisitions = None
524
+
525
+ if ngff_version is None:
526
+ ngff_version = self.version
527
+
528
+ return NgioPlateMeta(
529
+ plate=PlateWithVersion(
530
+ rows=rows,
531
+ columns=columns,
532
+ acquisitions=acquisitions,
533
+ wells=[],
534
+ field_count=self.plate.field_count,
535
+ name=name,
536
+ version=ngff_version,
537
+ ),
538
+ version=ngff_version,
539
+ )