@@ -24,6 +24,40 @@ class ViewConfiguration(dataclass.StateDataModel):
2424 swap_group : list [dict [str , str ]] = dataclass .Sync (list [dict [str , str ]], list )
2525
2626
27+ class CompareColormapConfig (ColormapConfig ):
28+ def __init__ (self , * args , default_range_fn , ** kwargs ):
29+ self ._default_range_fn = default_range_fn
30+ super ().__init__ (* args , ** kwargs )
31+
32+ def update_color_range (self ):
33+ if self .override_range :
34+ nan_min = math .isnan (self .color_range [0 ])
35+ nan_max = math .isnan (self .color_range [1 ])
36+ if nan_min :
37+ self .color_value_min_valid = False
38+ if nan_max :
39+ self .color_value_max_valid = False
40+ if nan_min or nan_max :
41+ return
42+ else :
43+ data_range = self ._default_range_fn ()
44+ if data_range is not None :
45+ self .color_range = data_range
46+ self .color_value_min = str (data_range [0 ])
47+ self .color_value_max = str (data_range [1 ])
48+ self .color_value_min_valid = True
49+ self .color_value_max_valid = True
50+
51+ self .update_color_preset (
52+ self .preset ,
53+ self .invert ,
54+ self .use_log_scale ,
55+ self .discrete_log ,
56+ self .n_discrete_colors ,
57+ self .n_ticks ,
58+ )
59+
60+
2761class VariableView (TrameComponent ):
2862 def __init__ (self , server , source , view_spec , variable_type , camera ):
2963 super ().__init__ (server )
@@ -63,18 +97,17 @@ def __init__(self, server, source, view_spec, variable_type, camera):
6397 self .renderer .AddActor (self .actor )
6498
6599 # Lookup table color management
66- self .colormap = ColormapConfig (
100+ self .colormap = CompareColormapConfig (
67101 server ,
68102 mapper = self .mapper ,
69103 data_array_fn = lambda : self ._get_data_array (self .array_name ),
104+ default_range_fn = self ._get_default_range ,
70105 ).set_data_array (
71106 self .array_name , lambda : self ._get_data_array (self .array_name ), "cell"
72107 )
108+ self ._sync_diverging_mode ()
73109 self .colormap .watch (["mapper_change" ], lambda * _ : self .render ())
74110
75- if self .role in ("diff" , "comp1" , "comp2" ):
76- self .colormap .diverging = True
77-
78111 self ._connect_pipeline_input ()
79112
80113 # Add shared annotation actors
@@ -102,8 +135,20 @@ def update_view_spec(self, view_spec):
102135 self .display_label = view_spec ["label" ]
103136 self .config .base_variable = self .base_variable
104137 self .config .label = self .display_label
138+ self ._sync_diverging_mode ()
105139 self ._connect_pipeline_input ()
106140
141+ def _sync_diverging_mode (self ):
142+ is_diverging = self .role in ("diff" , "comp1" , "comp2" )
143+ self .colormap .diverging = is_diverging
144+
145+ # The generic diverging handler forces override_range=True so the
146+ # symmetric range it computes will stick. CompareView needs diverging
147+ # presets/ticks, but it also needs slice-driven ranges to recompute
148+ # from paired control/test data when override_range is not user-set.
149+ if is_diverging :
150+ self .colormap .override_range = False
151+
107152 @property
108153 def bounds (self ):
109154 return self .state [self ._bounds_key ]
0 commit comments