1+ from __future__ import annotations
2+
13from collections import OrderedDict , namedtuple
24from typing import Any , Dict , List , Optional , Sequence , Union
35from warnings import warn
1517
1618def _sanitize_frame (frame ):
1719 if se ._frameutils .is_pandas (frame ):
18- frame = biocframe .from_pandas (frame )
20+ frame = biocframe .BiocFrame . from_pandas (frame )
1921
2022 return frame
2123
@@ -121,7 +123,7 @@ def _create_smap_from_experiments(experiments):
121123 return col_data , sample_map
122124
123125
124- class MultiAssayExperiment :
126+ class MultiAssayExperiment ( ut . BiocObject ) :
125127 """Container class for representing and managing multi-omics genomic experiments.
126128
127129 Checkout the
@@ -132,10 +134,10 @@ class MultiAssayExperiment:
132134 def __init__ (
133135 self ,
134136 experiments : Dict [str , Any ],
135- column_data : biocframe .BiocFrame = None ,
136- sample_map : biocframe .BiocFrame = None ,
137- metadata : Optional [dict ] = None ,
138- validate : bool = True ,
137+ column_data : Optional [ biocframe .BiocFrame ] = None ,
138+ sample_map : Optional [ biocframe .BiocFrame ] = None ,
139+ metadata : Optional [Union [ Dict [ str , Any ], ut . NamedList ] ] = None ,
140+ _validate : bool = True ,
139141 ) -> None :
140142 """Initialize an instance of ``MultiAssayExperiment``.
141143
@@ -194,11 +196,12 @@ def __init__(
194196 metadata:
195197 Additional study-level metadata. Defaults to None.
196198
197- validate :
199+ _validate :
198200 Internal use only.
199201 """
202+ super ().__init__ (metadata = metadata , _validate = _validate )
203+
200204 self ._experiments = experiments if experiments is not None else {}
201- self ._metadata = metadata if metadata is not None else {}
202205
203206 if sample_map is not None and column_data is not None :
204207 self ._sample_map = _sanitize_frame (sample_map )
@@ -211,17 +214,11 @@ def __init__(
211214 "Either 'sample_map' or 'column_data' is `None`. Either both should be provided or set both to `None`."
212215 )
213216
214- if validate :
217+ if _validate :
215218 _validate_experiments (self ._experiments )
216219 _validate_column_data (self ._column_data )
217220 _validate_sample_map (self ._sample_map , self ._column_data , self ._experiments )
218221
219- def _define_output (self , in_place : bool = False ) -> "MultiAssayExperiment" :
220- if in_place is True :
221- return self
222- else :
223- return self .__copy__ ()
224-
225222 #########################
226223 ######>> Copying <<######
227224 #########################
@@ -244,6 +241,7 @@ def __deepcopy__(self, memo=None, _nil=[]):
244241 column_data = _column_data_copy ,
245242 sample_map = _sample_map_copy ,
246243 metadata = _metadata_copy ,
244+ _validate = False ,
247245 )
248246
249247 def __copy__ (self ):
@@ -257,6 +255,7 @@ def __copy__(self):
257255 column_data = self ._column_data ,
258256 sample_map = self ._sample_map ,
259257 metadata = self ._metadata ,
258+ _validate = False ,
260259 )
261260
262261 def copy (self ):
@@ -321,7 +320,7 @@ def get_experiments(self) -> Dict[str, Any]:
321320
322321 return self ._experiments
323322
324- def set_experiments (self , experiments : Dict [str , Any ], in_place : bool = False ) -> " MultiAssayExperiment" :
323+ def set_experiments (self , experiments : Dict [str , Any ], in_place : bool = False ) -> MultiAssayExperiment :
325324 """Set new experiments.
326325
327326 Args:
@@ -387,7 +386,7 @@ def get_experiment_names(self) -> List[str]:
387386 """
388387 return list (self ._experiments .keys ())
389388
390- def set_experiment_names (self , names : List [str ], in_place : bool = False ) -> " MultiAssayExperiment" :
389+ def set_experiment_names (self , names : List [str ], in_place : bool = False ) -> MultiAssayExperiment :
391390 """Replace :py:attr:`~experiments`'s names.
392391
393392 Args:
@@ -513,7 +512,7 @@ def get_sample_map(self) -> biocframe.BiocFrame:
513512 """
514513 return self ._sample_map
515514
516- def set_sample_map (self , sample_map : biocframe .BiocFrame , in_place : bool = False ) -> " MultiAssayExperiment" :
515+ def set_sample_map (self , sample_map : biocframe .BiocFrame , in_place : bool = False ) -> MultiAssayExperiment :
517516 """Set new sample mapping.
518517
519518 Args:
@@ -563,7 +562,7 @@ def get_column_data(self) -> biocframe.BiocFrame:
563562 """
564563 return self ._column_data
565564
566- def set_column_data (self , column_data : biocframe .BiocFrame , in_place : bool = False ) -> " MultiAssayExperiment" :
565+ def set_column_data (self , column_data : biocframe .BiocFrame , in_place : bool = False ) -> MultiAssayExperiment :
567566 """Set new sample metadata.
568567
569568 Args:
@@ -603,54 +602,6 @@ def column_data(self, column_data: biocframe.BiocFrame):
603602 )
604603 self .set_column_data (column_data , in_place = True )
605604
606- ###########################
607- ######>> metadata <<#######
608- ###########################
609-
610- def get_metadata (self ) -> dict :
611- """
612- Returns:
613- Dictionary of metadata for this object.
614- """
615- return self ._metadata
616-
617- def set_metadata (self , metadata : dict , in_place : bool = False ) -> "MultiAssayExperiment" :
618- """Set additional metadata.
619-
620- Args:
621- metadata:
622- New metadata for this object.
623-
624- in_place:
625- Whether to modify the ``MultiAssayExperiment`` in place.
626-
627- Returns:
628- A modified ``MultiAssayExperiment`` object, either as a copy of the original
629- or as a reference to the (in-place-modified) original.
630- """
631- if not isinstance (metadata , dict ):
632- raise TypeError (f"`metadata` must be a dictionary, provided { type (metadata )} ." )
633- output = self ._define_output (in_place )
634- output ._metadata = metadata
635- return output
636-
637- @property
638- def metadata (self ) -> dict :
639- """Alias for :py:attr:`~get_metadata`."""
640- return self .get_metadata ()
641-
642- @metadata .setter
643- def metadata (self , metadata : dict ):
644- """Alias for :py:attr:`~set_metadata` with ``in_place = True``.
645-
646- As this mutates the original object, a warning is raised.
647- """
648- warn (
649- "Setting property 'metadata' is an in-place operation, use 'set_metadata' instead" ,
650- UserWarning ,
651- )
652- self .set_metadata (metadata , in_place = True )
653-
654605 #########################
655606 ######>> subset <<#######
656607 #########################
@@ -812,7 +763,7 @@ def _generic_slice(
812763
813764 return SlicerResult (_new_experiments , _new_sample_map , _new_column_data )
814765
815- def subset_by_experiments (self , experiments : Union [str , int , bool , Sequence ]) -> " MultiAssayExperiment" :
766+ def subset_by_experiments (self , experiments : Union [str , int , bool , Sequence ]) -> MultiAssayExperiment :
816767 """Subset by experiment(s).
817768
818769 Args:
@@ -831,7 +782,7 @@ def subset_by_experiments(self, experiments: Union[str, int, bool, Sequence]) ->
831782 sresult = self ._generic_slice (experiments = experiments )
832783 return MultiAssayExperiment (sresult .experiments , sresult .column_data , sresult .sample_map , self .metadata )
833784
834- def subset_by_row (self , rows : Union [str , int , bool , Sequence ]) -> " MultiAssayExperiment" :
785+ def subset_by_row (self , rows : Union [str , int , bool , Sequence ]) -> MultiAssayExperiment :
835786 """Subset by rows.
836787
837788 Args:
@@ -848,7 +799,7 @@ def subset_by_row(self, rows: Union[str, int, bool, Sequence]) -> "MultiAssayExp
848799 sresult = self ._generic_slice (rows = rows )
849800 return MultiAssayExperiment (sresult .experiments , sresult .column_data , sresult .sample_map , self .metadata )
850801
851- def subset_by_column (self , columns : Union [str , int , bool , Sequence ]) -> " MultiAssayExperiment" :
802+ def subset_by_column (self , columns : Union [str , int , bool , Sequence ]) -> MultiAssayExperiment :
852803 """Subset by column.
853804
854805 Args:
@@ -865,7 +816,7 @@ def subset_by_column(self, columns: Union[str, int, bool, Sequence]) -> "MultiAs
865816 sresult = self ._generic_slice (columns = columns )
866817 return MultiAssayExperiment (sresult .experiments , sresult .column_data , sresult .sample_map , self .metadata )
867818
868- def __getitem__ (self , args : tuple ) -> " MultiAssayExperiment" :
819+ def __getitem__ (self , args : tuple ) -> MultiAssayExperiment :
869820 """Subset a `MultiAssayExperiment`.
870821
871822 Args:
@@ -988,7 +939,7 @@ def find_common_row_names(self) -> List[str]:
988939
989940 return _common
990941
991- def intersect_rows (self ) -> " MultiAssayExperiment" :
942+ def intersect_rows (self ) -> MultiAssayExperiment :
992943 """Finds common row names across all experiments and filters the MAE to these rows.
993944
994945 Returns:
@@ -1060,7 +1011,7 @@ def add_experiment(
10601011 sample_map : biocframe .BiocFrame ,
10611012 column_data : Optional [biocframe .BiocFrame ] = None ,
10621013 in_place : bool = False ,
1063- ) -> " MultiAssayExperiment" :
1014+ ) -> MultiAssayExperiment :
10641015 """Add a new experiment to `MultiAssayExperiment`.
10651016
10661017 ``sample_map`` must be provided to map the columns from this experiment to
@@ -1155,7 +1106,7 @@ def to_mudata(self):
11551106 return MuData (exptsList )
11561107
11571108 @classmethod
1158- def from_mudata (cls , input : "mudata.MuData" ) -> " MultiAssayExperiment" :
1109+ def from_mudata (cls , input : "mudata.MuData" ) -> MultiAssayExperiment :
11591110 """Create a ``MultiAssayExperiment`` object from :py:class:`~mudata.MuData`.
11601111
11611112 The import naively creates sample mapping, each ``experiment`` is considered to be a `sample`.
@@ -1215,7 +1166,7 @@ def from_mudata(cls, input: "mudata.MuData") -> "MultiAssayExperiment":
12151166 )
12161167
12171168 @classmethod
1218- def from_anndata (cls , input : "anndata.AnnData" , name : str = "unknown" ) -> " MultiAssayExperiment" :
1169+ def from_anndata (cls , input : "anndata.AnnData" , name : str = "unknown" ) -> MultiAssayExperiment :
12191170 """Create a ``MultiAssayExperiment`` from :py:class:`~anndata.AnnData`.
12201171
12211172 Since :py:class:`~anndata.AnnData` does not contain sample information,
0 commit comments