@@ -524,7 +524,6 @@ def __init__(self, parent, data_scrollbar):
524
524
gradient_map = dict (available_gradients )
525
525
526
526
527
-
528
527
class ArrayEditorWidget (QWidget ):
529
528
def __init__ (self , parent , data = None , readonly = False , bg_value = None , bg_gradient = 'blue-red' ,
530
529
minvalue = None , maxvalue = None ):
@@ -756,19 +755,21 @@ def dropEvent(self, event):
756
755
757
756
def set_data (self , data = None , bg_value = None ):
758
757
# update adapter
759
- self .data_adapter .set_data (data , bg_value = bg_value )
760
- la_data = self .data_adapter .get_data ()
761
- axes = la_data .axes
758
+ if data is None :
759
+ data = la .LArray ([])
760
+ else :
761
+ data = la .aslarray (data )
762
+ axes = data .axes
762
763
display_names = axes .display_names
763
764
764
- # update data format and bgcolor
765
- self ._update_digits_scientific (la_data )
765
+ # update data format
766
+ self ._update_digits_scientific (data )
766
767
767
768
# update filters
768
769
filters_layout = self .filters_layout
769
770
clear_layout (filters_layout )
770
771
# data.size > 0 to avoid arrays with length 0 axes and len(axes) > 0 to avoid scalars (scalar.size == 1)
771
- if la_data .size > 0 and len (axes ) > 0 :
772
+ if data .size > 0 and len (axes ) > 0 :
772
773
filters_layout .addWidget (QLabel (_ ("Filters" )))
773
774
for axis , display_name in zip (axes , display_names ):
774
775
filters_layout .addWidget (QLabel (display_name ))
@@ -779,87 +780,96 @@ def set_data(self, data=None, bg_value=None):
779
780
else :
780
781
filters_layout .addWidget (QLabel ("too big to be filtered" ))
781
782
filters_layout .addStretch ()
782
- self .data_adapter .update_filtered_data ({})
783
+
784
+ self .gradient_chooser .setEnabled (self .model_data .bgcolor_possible )
785
+
786
+ self .data_adapter .set_data (data , bg_value = bg_value )
783
787
784
788
# reset default size
785
789
self .view_axes .set_default_size ()
786
790
self .view_ylabels .set_default_size ()
787
791
self .view_xlabels .set_default_size ()
788
792
self .view_data .set_default_size ()
789
793
790
- def _update_digits_scientific (self , data ):
794
+ # called by set_data and ArrayEditorWidget.accept_changes (this should not be the case IMO)
795
+ # two cases:
796
+ # * set_data should update both scientific and ndigits
797
+ # * toggling scientific checkbox should update only ndigits
798
+ def _update_digits_scientific (self , data , scientific = None ):
791
799
"""
792
800
data : LArray
793
801
"""
794
- # TODO: Adapter must provide a method to return a data sample as a Numpy array
795
- assert isinstance (data , la .LArray )
796
- data = data .data
797
- size , dtype = data .size , data .dtype
798
- # this will yield a data sample of max 199
799
- step = (size // 100 ) if size > 100 else 1
800
- data_sample = data .flat [::step ]
801
-
802
- # TODO: refactor so that the expensive format_helper is not called
803
- # twice (or the values are cached)
804
- use_scientific = self .choose_scientific (data_sample )
802
+ dtype = data .dtype
803
+ if dtype .type in (np .str , np .str_ , np .bool_ , np .bool , np .object_ ):
804
+ scientific = False
805
+ ndecimals = 0
806
+ else :
807
+ # XXX: move this to the adapter (return a data sample as a Numpy array)
808
+ data = self ._get_sample (data )
809
+
810
+ # max_digits = self.get_max_digits()
811
+ # default width can fit 8 chars
812
+ # FIXME: use max_digits?
813
+ avail_digits = 8
814
+ frac_zeros , int_digits , has_negative = self .format_helper (data )
815
+
816
+ # choose whether or not to use scientific notation
817
+ # ================================================
818
+ if scientific is None :
819
+ # use scientific format if there are more integer digits than we can display or if we can display more
820
+ # information that way (scientific format "uses" 4 digits, so we have a net win if we have >= 4 zeros --
821
+ # *including the integer one*)
822
+ # TODO: only do so if we would actually display more information
823
+ # 0.00001 can be displayed with 8 chars
824
+ # 1e-05
825
+ # would
826
+ scientific = int_digits > avail_digits or frac_zeros >= 4
827
+
828
+ # determine best number of decimals to display
829
+ # ============================================
830
+ # TODO: ndecimals vs self.digits => rename self.digits to either frac_digits or ndecimals
831
+ data_frac_digits = self ._data_digits (data )
832
+ if scientific :
833
+ int_digits = 2 if has_negative else 1
834
+ exp_digits = 4
835
+ else :
836
+ exp_digits = 0
837
+ # - 1 for the dot
838
+ ndecimals = avail_digits - 1 - int_digits - exp_digits
805
839
806
- # XXX: self.ndecimals vs self.digits
807
- self .digits = self .choose_ndecimals (data_sample , use_scientific )
808
- self .use_scientific = use_scientific
809
- self .model_data .set_format (self .cell_format )
840
+ if ndecimals < 0 :
841
+ ndecimals = 0
810
842
811
- self . digits_spinbox . setValue ( self . digits )
812
- self . digits_spinbox . setEnabled ( is_number ( dtype ))
843
+ if data_frac_digits < ndecimals :
844
+ ndecimals = data_frac_digits
813
845
814
- self .scientific_checkbox .setChecked (use_scientific )
815
- self .scientific_checkbox .setEnabled (is_number (dtype ))
846
+ self .digits = ndecimals
816
847
817
- self .gradient_chooser . setEnabled ( self . model_data . bgcolor_possible )
848
+ self .use_scientific = scientific
818
849
819
- def choose_scientific (self , data ):
820
- # max_digits = self.get_max_digits()
821
- # default width can fit 8 chars
822
- # FIXME: use max_digits?
823
- avail_digits = 8
824
- if data .dtype .type in (np .str , np .str_ , np .bool_ , np .bool , np .object_ ):
825
- return False
826
-
827
- frac_zeros , int_digits , _ = self .format_helper (data )
828
-
829
- # if there are more integer digits than we can display or we can
830
- # display more information by using scientific format, do so
831
- # (scientific format "uses" 4 digits, so we win if have >= 4 zeros
832
- # -- *including the integer one*)
833
- # TODO: only do so if we would actually display more information
834
- # 0.00001 can be displayed with 8 chars
835
- # 1e-05
836
- # would
837
- return int_digits > avail_digits or frac_zeros >= 4
838
-
839
- def choose_ndecimals (self , data , scientific ):
840
- if data .dtype .type in (np .str , np .str_ , np .bool_ , np .bool , np .object_ ):
841
- return 0
850
+ self .digits_spinbox .blockSignals (True )
851
+ self .digits_spinbox .setValue (ndecimals )
852
+ self .digits_spinbox .setEnabled (is_number (dtype ))
853
+ self .digits_spinbox .blockSignals (False )
842
854
843
- # max_digits = self.get_max_digits()
844
- # default width can fit 8 chars
845
- # FIXME: use max_digits?
846
- avail_digits = 8
847
- data_frac_digits = self ._data_digits (data )
848
- _ , int_digits , negative = self .format_helper (data )
849
- if scientific :
850
- int_digits = 2 if negative else 1
851
- exp_digits = 4
852
- else :
853
- exp_digits = 0
854
- # - 1 for the dot
855
- ndecimals = avail_digits - 1 - int_digits - exp_digits
855
+ self .scientific_checkbox .blockSignals (True )
856
+ self .scientific_checkbox .setChecked (scientific )
857
+ self .scientific_checkbox .setEnabled (is_number (dtype ))
858
+ self .scientific_checkbox .blockSignals (False )
856
859
857
- if ndecimals < 0 :
858
- ndecimals = 0
860
+ # setting the format explicitly instead of relying on digits_spinbox.digits_changed to set it because
861
+ # digits_changed is only triggered when digits actually changed, not when passing from scientific -> non
862
+ # scientific or number -> object
863
+ self .model_data .set_format (self .cell_format )
859
864
860
- if data_frac_digits < ndecimals :
861
- ndecimals = data_frac_digits
862
- return ndecimals
865
+ def _get_sample (self , data ):
866
+ assert isinstance (data , la .LArray )
867
+ data = data .data
868
+ size = data .size
869
+ # this will yield a data sample of max 199
870
+ step = (size // 100 ) if size > 100 else 1
871
+ sample = data .flat [::step ]
872
+ return sample [np .isfinite (sample )]
863
873
864
874
def format_helper (self , data ):
865
875
if not data .size :
@@ -963,10 +973,7 @@ def cell_format(self):
963
973
return '%%.%d%s' % (self .digits , format_letter )
964
974
965
975
def scientific_changed (self , value ):
966
- self .use_scientific = value
967
- self .digits = self .choose_ndecimals (self .data_adapter .get_data (), value )
968
- self .digits_spinbox .setValue (self .digits )
969
- self .model_data .set_format (self .cell_format )
976
+ self ._update_digits_scientific (self .data_adapter .get_data (), value )
970
977
971
978
def digits_changed (self , value ):
972
979
self .digits = value
0 commit comments