22
33import pathlib
44import warnings
5- from itertools import count
5+ from contextlib import suppress
66from typing import Any
77
88import numpy as np
1818
1919
2020# Create a counter for each model
21- background_number = count (1 )
22- contrast_number = count (1 )
23- custom_file_number = count (1 )
24- data_number = count (1 )
25- domain_contrast_number = count (1 )
26- layer_number = count (1 )
27- parameter_number = count (1 )
28- resolution_number = count (1 )
21+ background_number = ["Background" , 0 ]
22+ contrast_number = ["Contrast" , 0 ]
23+ custom_file_number = ["Custom File" , 0 ]
24+ data_number = ["Data" , 0 ]
25+ domain_contrast_number = ["Domain Contrast" , 0 ]
26+ layer_number = ["Layer" , 0 ]
27+ parameter_number = ["Parameter" , 0 ]
28+ resolution_number = ["Resolution" , 0 ]
29+
30+ _model_counter = {
31+ "Background" : background_number ,
32+ "Contrast" : contrast_number ,
33+ "ContrastWithRatio" : contrast_number ,
34+ "CustomFile" : custom_file_number ,
35+ "Data" : data_number ,
36+ "DomainContrast" : domain_contrast_number ,
37+ "Layer" : layer_number ,
38+ "AbsorptionLayer" : layer_number ,
39+ "Parameter" : parameter_number ,
40+ "ProtectedParameter" : parameter_number ,
41+ "Resolution" : resolution_number ,
42+ }
43+
44+
45+ def _model_name_factory (model_name : str ) -> str :
46+ """Generate a unique name for model using a global counter.
47+
48+ Parameters
49+ ----------
50+ model_name : str
51+ The name of the model class.
52+ """
53+ title , number = _model_counter [model_name ]
54+ _model_counter [model_name ][1 ] += 1
55+ return f"New { title } { (number + 1 )} "
2956
3057
3158class RATModel (BaseModel , validate_assignment = True , extra = "forbid" ):
@@ -38,6 +65,25 @@ def __repr__(self):
3865 )
3966 return f"{ self .__repr_name__ ()} ({ fields_repr } )"
4067
68+ @field_validator ("name" , mode = "after" , check_fields = False )
69+ @classmethod
70+ def update_counter (cls , name : str ) -> str :
71+ """Update the auto name counter if a similar name is manually given.
72+
73+ Parameters
74+ ----------
75+ name : str
76+ The name of the model.
77+ """
78+ title , number = _model_counter [cls .__name__ ]
79+ prefix = f"New { title } "
80+ if name .startswith (prefix ):
81+ with suppress (ValueError ):
82+ new_number = int (name [len (prefix ) :])
83+ if new_number > number :
84+ _model_counter [cls .__name__ ][1 ] = new_number
85+ return name
86+
4187 def __str__ (self ):
4288 table = prettytable .PrettyTable ()
4389 table .field_names = [key .replace ("_" , " " ) for key in self .display_fields ]
@@ -116,7 +162,7 @@ class Background(Signal):
116162
117163 """
118164
119- name : str = Field (default_factory = lambda : f"New Background { next ( background_number ) } " , min_length = 1 )
165+ name : str = Field (default_factory = lambda : _model_name_factory ( " Background" ) , min_length = 1 )
120166
121167 @model_validator (mode = "after" )
122168 def check_unsupported_parameters (self ):
@@ -173,7 +219,7 @@ class Contrast(RATModel):
173219
174220 """
175221
176- name : str = Field (default_factory = lambda : f"New Contrast { next ( contrast_number ) } " , min_length = 1 )
222+ name : str = Field (default_factory = lambda : _model_name_factory ( " Contrast" ) , min_length = 1 )
177223 data : str = ""
178224 background : str = ""
179225 background_action : BackgroundActions = BackgroundActions .Add
@@ -255,7 +301,7 @@ class ContrastWithRatio(RATModel):
255301
256302 """
257303
258- name : str = Field (default_factory = lambda : f"New Contrast { next ( contrast_number ) } " , min_length = 1 )
304+ name : str = Field (default_factory = lambda : _model_name_factory ( "ContrastWithRatio" ) , min_length = 1 )
259305 data : str = ""
260306 background : str = ""
261307 background_action : BackgroundActions = BackgroundActions .Add
@@ -309,7 +355,7 @@ class CustomFile(RATModel):
309355
310356 """
311357
312- name : str = Field (default_factory = lambda : f"New Custom File { next ( custom_file_number ) } " , min_length = 1 )
358+ name : str = Field (default_factory = lambda : _model_name_factory ( "CustomFile" ) , min_length = 1 )
313359 filename : str = ""
314360 function_name : str = ""
315361 language : Languages = Languages .Python
@@ -348,7 +394,7 @@ class Data(RATModel, arbitrary_types_allowed=True):
348394
349395 """
350396
351- name : str = Field (default_factory = lambda : f"New Data { next ( data_number ) } " , min_length = 1 )
397+ name : str = Field (default_factory = lambda : _model_name_factory ( " Data" ) , min_length = 1 )
352398 data : np .ndarray = np .empty ([0 , 3 ])
353399 data_range : list [float ] = Field (default = [], min_length = 2 , max_length = 2 )
354400 simulation_range : list [float ] = Field (default = [], min_length = 2 , max_length = 2 )
@@ -453,7 +499,7 @@ class DomainContrast(RATModel):
453499
454500 """
455501
456- name : str = Field (default_factory = lambda : f"New Domain Contrast { next ( domain_contrast_number ) } " , min_length = 1 )
502+ name : str = Field (default_factory = lambda : _model_name_factory ( "DomainContrast" ) , min_length = 1 )
457503 model : list [str ] = []
458504
459505 def __str__ (self ):
@@ -483,7 +529,7 @@ class Layer(RATModel, populate_by_name=True):
483529
484530 """
485531
486- name : str = Field (default_factory = lambda : f"New Layer { next ( layer_number ) } " , min_length = 1 )
532+ name : str = Field (default_factory = lambda : _model_name_factory ( " Layer" ) , min_length = 1 )
487533 thickness : str
488534 SLD : str = Field (validation_alias = "SLD_real" )
489535 roughness : str
@@ -522,7 +568,7 @@ class AbsorptionLayer(RATModel, populate_by_name=True):
522568
523569 """
524570
525- name : str = Field (default_factory = lambda : f"New Layer { next ( layer_number ) } " , min_length = 1 )
571+ name : str = Field (default_factory = lambda : _model_name_factory ( "AbsorptionLayer" ) , min_length = 1 )
526572 thickness : str
527573 SLD_real : str = Field (validation_alias = "SLD" )
528574 SLD_imaginary : str
@@ -555,7 +601,7 @@ class Parameter(RATModel):
555601
556602 """
557603
558- name : str = Field (default_factory = lambda : f"New Parameter { next ( parameter_number ) } " , min_length = 1 )
604+ name : str = Field (default_factory = lambda : _model_name_factory ( " Parameter" ) , min_length = 1 )
559605 min : float = 0.0
560606 value : float = 0.0
561607 max : float = 0.0
@@ -638,7 +684,7 @@ class Resolution(Signal):
638684
639685 """
640686
641- name : str = Field (default_factory = lambda : f"New Resolution { next ( resolution_number ) } " , min_length = 1 )
687+ name : str = Field (default_factory = lambda : _model_name_factory ( " Resolution" ) , min_length = 1 )
642688
643689 @field_validator ("type" )
644690 @classmethod
0 commit comments