@@ -102,6 +102,20 @@ def valid_hex_color(v: str) -> bool:
102102 return True
103103
104104
105+ def into_valid_hex_color (v : str ) -> str :
106+ """Convert a string into a valid hexadecimal color.
107+
108+ If the string is already a valid hexadecimal color, return it.
109+ Otherwise, return a hexadecimal color based on the hash of the string.
110+ """
111+ # strip leading '#' if present
112+ v = v .lstrip ("#" )
113+ if valid_hex_color (v ):
114+ return v
115+
116+ return NgioColors .semi_random_pick (v .lower ()).value
117+
118+
105119class ChannelVisualisation (BaseModel ):
106120 """Channel visualisation model.
107121
@@ -135,13 +149,10 @@ def validate_color(cls, value: str | NgioColors) -> str:
135149 """
136150 if value is None :
137151 return NgioColors .semi_random_pick ().value
138- if isinstance (value , str ) and valid_hex_color ( value ) :
139- return value
152+ if isinstance (value , str ):
153+ return into_valid_hex_color ( value )
140154 elif isinstance (value , NgioColors ):
141155 return value .value
142- elif isinstance (value , str ):
143- value_lower = value .lower ()
144- return NgioColors .semi_random_pick (value_lower ).value
145156 else :
146157 raise NgioValueError (f"Invalid color { value } ." )
147158
@@ -159,19 +170,6 @@ def check_start_end(cls, data):
159170 data ["end" ] = start + 1
160171 return data
161172
162- @model_validator (mode = "after" )
163- def check_model (self ) -> "ChannelVisualisation" :
164- """Check that the start and end values are within the min and max values."""
165- if self .start < self .min or self .start > self .max :
166- raise NgioValidationError (
167- f"Start value { self .start } is out of range [{ self .min } , { self .max } ]"
168- )
169- if self .end < self .min or self .end > self .max :
170- raise NgioValidationError (
171- f"End value { self .end } is out of range [{ self .min } , { self .max } ]"
172- )
173- return self
174-
175173 @classmethod
176174 def default_init (
177175 cls ,
0 commit comments