8
8
from scipy import optimize as sopt
9
9
from enum import Enum
10
10
from types import NoneType
11
- from typing import Type
11
+ from typing import Type , Self
12
12
from pyNexafs .nexafs .scan import scan_base , scan_abstract
13
13
14
14
@@ -22,12 +22,26 @@ class scan_abstract_normalised(scan_abstract, metaclass=abc.ABCMeta):
22
22
A scan object. Could be already normalised scan or a scan_base object.
23
23
"""
24
24
25
- def __init__ (self , scan : Type [ scan_abstract ] ):
25
+ def __init__ (self , scan : scan_abstract ):
26
26
self ._origin = scan
27
27
return
28
28
29
+ @overrides .overrides
30
+ @abc .abstractmethod
31
+ def copy (self ) -> scan_abstract_normalised :
32
+ """
33
+ Returns a copy of the scan object.
34
+
35
+ Returns
36
+ -------
37
+ scan_abstract
38
+ A copy of the scan object.
39
+ """
40
+ copy_obj = type (self )(scan = self ._origin )
41
+ return copy_obj
42
+
29
43
@property
30
- def origin (self ) -> Type [ scan_base ] :
44
+ def origin (self ) -> scan_abstract :
31
45
"""
32
46
Property for the original scan object.
33
47
@@ -113,7 +127,7 @@ def x_label(self) -> str:
113
127
return self .origin .x_label
114
128
115
129
@x_label .setter
116
- def x_label (self , label : str ) -> None :
130
+ def x_label (self , label : str | None ) -> None :
117
131
"""
118
132
Property setter for the x-axis label, to the origin scan.
119
133
@@ -223,7 +237,7 @@ def y_units(self) -> list[str]:
223
237
return self .origin .y_units
224
238
225
239
@y_units .setter
226
- def y_units (self , units : list [str ]) -> None :
240
+ def y_units (self , units : list [str ] | None ) -> None :
227
241
"""
228
242
Property setter for the y-axis units, to the origin scan.
229
243
@@ -245,8 +259,12 @@ def __init__(
245
259
raise ValueError ("X data for scan and background scan do not match." )
246
260
if scan .y .shape != scan_background .y .shape :
247
261
raise ValueError ("Y data for scan and background scan do not match." )
248
- self ._origin = scan
262
+
263
+ super ().__init__ (scan )
249
264
self ._background = scan_background
265
+
266
+ # Run the normalisation
267
+ self .load_and_normalise ()
250
268
return
251
269
252
270
@overrides .overrides
@@ -287,6 +305,10 @@ def _scale_from_normalisation_data(self) -> None:
287
305
)
288
306
return
289
307
308
+ @overrides .overrides
309
+ def copy (self ) -> scan_background_subtraction :
310
+ return scan_background_subtraction (self ._origin , self ._background )
311
+
290
312
291
313
class scan_normalised (scan_abstract_normalised ):
292
314
"""
@@ -585,6 +607,17 @@ def y_units(self, units: list[str] | None) -> None:
585
607
self ._origin .y_units = units
586
608
return
587
609
610
+ def copy (self ) -> Self :
611
+ """
612
+ Returns a copy of the scan object.
613
+
614
+ Returns
615
+ -------
616
+ scan_abstract
617
+ A copy of the scan object.
618
+ """
619
+ return scan_normalised (self ._origin , norm_channel = self ._norm_channel )
620
+
588
621
589
622
class scan_normalised_background_channel (scan_normalised ):
590
623
"""
@@ -599,8 +632,8 @@ class scan_normalised_background_channel(scan_normalised):
599
632
@overrides .overrides
600
633
def __init__ (
601
634
self ,
602
- scan : Type [ scan_abstract ] ,
603
- background_scan : Type [ scan_abstract ] ,
635
+ scan : scan_abstract ,
636
+ background_scan : scan_abstract ,
604
637
norm_channel : str ,
605
638
) -> None :
606
639
# Save background scan and channel information
@@ -619,7 +652,8 @@ def __init__(
619
652
@overrides .overrides
620
653
def _load_from_origin (self ):
621
654
# Reload background_scan data
622
- self ._background_scan .load_from_origin ()
655
+ if hasattr (self ._background_scan , "_load_from_origin" ):
656
+ self ._background_scan .load_from_origin ()
623
657
# Reload scan data
624
658
super ()._load_from_origin ()
625
659
@@ -746,9 +780,9 @@ class POSTEDGE_NORM_TYPE(Enum):
746
780
747
781
def __init__ (
748
782
self ,
749
- scan : Type [scan_base ],
750
- pre_edge_domain = list [int ] | tuple [float , float ] | None ,
751
- post_edge_domain = list [int ] | tuple [float , float ] | None ,
783
+ scan : Type [scan_abstract ],
784
+ pre_edge_domain : list [int ] | tuple [float , float ] | None ,
785
+ post_edge_domain : list [int ] | tuple [float , float ] | None ,
752
786
pre_edge_normalisation : PREEDGE_NORM_TYPE = PREEDGE_NORM_TYPE .CONSTANT ,
753
787
post_edge_normalisation : POSTEDGE_NORM_TYPE = POSTEDGE_NORM_TYPE .CONSTANT ,
754
788
pre_edge_level : float | None = None ,
@@ -780,6 +814,19 @@ def __init__(
780
814
self .load_and_normalise ()
781
815
return
782
816
817
+ @overrides .overrides
818
+ def copy (self ) -> scan_normalised_edges :
819
+ clone = scan_normalised_edges (
820
+ self ._origin ,
821
+ pre_edge_domain = self ._pre_edge_domain ,
822
+ post_edge_domain = self ._post_edge_domain ,
823
+ pre_edge_normalisation = self .pre_edge_normalisation ,
824
+ post_edge_normalisation = self .post_edge_normalisation ,
825
+ pre_edge_level = self ._pre_edge_level ,
826
+ post_edge_level = self ._post_edge_level ,
827
+ )
828
+ return clone
829
+
783
830
@overrides .overrides
784
831
def _scale_from_normalisation_data (self ) -> None :
785
832
"""
@@ -811,7 +858,9 @@ def _scale_from_normalisation_data(self) -> None:
811
858
).nonzero ()
812
859
# Check indexes of each tuple element
813
860
if len (pre_inds [0 ]) == 0 :
814
- raise ValueError ("Pre-edge domain is empty." )
861
+ raise ValueError (
862
+ f"Pre-edge domain ({ self .pre_edge_domain [0 ]} to { self .pre_edge_domain [1 ]} ) contains no datapoints."
863
+ )
815
864
else :
816
865
raise AttributeError (
817
866
"Pre-edge domain is not defined correctly. Should be a list of indexes or the range in a tuple."
@@ -879,15 +928,17 @@ def _scale_from_normalisation_data(self) -> None:
879
928
if isinstance (self .post_edge_domain , list ):
880
929
post_inds = self .post_edge_domain
881
930
if len (post_inds ) == 0 :
882
- raise ValueError ("Pre -edge index list is empty." )
931
+ raise ValueError ("Post -edge index list is empty." )
883
932
elif isinstance (self .post_edge_domain , tuple ):
884
933
post_inds = np .where (
885
934
(self .x >= self .post_edge_domain [0 ])
886
935
& (self .x <= self .post_edge_domain [1 ])
887
936
)
888
937
# Check indexes of each tuple element
889
938
if len (post_inds [0 ]) == 0 :
890
- raise ValueError ("Pre-edge domain is empty." )
939
+ raise ValueError (
940
+ f"Post-edge domain ({ self .post_edge_domain [0 ]} to { self .post_edge_domain [1 ]} ) contains no datapoints."
941
+ )
891
942
else :
892
943
raise AttributeError (
893
944
"Post-edge domain is not defined correctly. Should be a list of indexes or the range in a tuple."
0 commit comments