@@ -595,6 +595,7 @@ def _parse_get_trace_props(
595
595
hf_y : Iterable = None ,
596
596
hf_text : Iterable = None ,
597
597
hf_hovertext : Iterable = None ,
598
+ check_nans : bool = True ,
598
599
) -> _hf_data_container :
599
600
"""Parse and capture the possibly high-frequency trace-props in a datacontainer.
600
601
@@ -603,14 +604,19 @@ def _parse_get_trace_props(
603
604
trace : BaseTraceType
604
605
The trace which will be parsed.
605
606
hf_x : Iterable, optional
606
- high -frequency trace "x" data, overrides the current trace its x-data.
607
+ High -frequency trace "x" data, overrides the current trace its x-data.
607
608
hf_y : Iterable, optional
608
- high -frequency trace "y" data, overrides the current trace its y-data.
609
+ High -frequency trace "y" data, overrides the current trace its y-data.
609
610
hf_text : Iterable, optional
610
- high -frequency trace "text" data, overrides the current trace its text-data.
611
+ High -frequency trace "text" data, overrides the current trace its text-data.
611
612
hf_hovertext : Iterable, optional
612
- high -frequency trace "hovertext" data, overrides the current trace its
613
+ High -frequency trace "hovertext" data, overrides the current trace its
613
614
hovertext data.
615
+ check_nans: bool, optional
616
+ Whether the `hf_y` should be checked for NaNs, by default True.
617
+ As checking for NaNs is expensive, this can be disabled when the `hf_y` is
618
+ already known to contain no NaNs (or when the downsampler can handle NaNs,
619
+ e.g., EveryNthPoint).
614
620
615
621
Returns
616
622
-------
@@ -680,7 +686,7 @@ def _parse_get_trace_props(
680
686
# Remove NaNs for efficiency (storing less meaningless data)
681
687
# NaNs introduce gaps between enclosing non-NaN data points & might distort
682
688
# the resampling algorithms
683
- if pd .isna (hf_y ).any ():
689
+ if check_nans and pd .isna (hf_y ).any ():
684
690
not_nan_mask = ~ pd .isna (hf_y )
685
691
hf_x = hf_x [not_nan_mask ]
686
692
hf_y = hf_y [not_nan_mask ]
@@ -843,6 +849,7 @@ def add_trace(
843
849
hf_y : Iterable = None ,
844
850
hf_text : Union [str , Iterable ] = None ,
845
851
hf_hovertext : Union [str , Iterable ] = None ,
852
+ check_nans : bool = True ,
846
853
** trace_kwargs ,
847
854
):
848
855
"""Add a trace to the figure.
@@ -870,7 +877,7 @@ def add_trace(
870
877
.. note::
871
878
If this variable is not set, ``_global_downsampler`` will be used.
872
879
limit_to_view: boolean, optional
873
- If set to True the trace's datapoints will be cut to the corresponding
880
+ If set to True, the trace's datapoints will be cut to the corresponding
874
881
front-end view, even if the total number of samples is lower than
875
882
``max_n_samples``, By default False.\n
876
883
Remark that setting this parameter to True ensures that low frequency traces
@@ -888,6 +895,13 @@ def add_trace(
888
895
hf_hovertext: Iterable, optional
889
896
The original high frequency hovertext. If set, this has priority over the
890
897
trace its ```hovertext`` argument.
898
+ check_nans: boolean, optional
899
+ If set to True, the trace's data will be checked for NaNs - which will be
900
+ removed. By default True.
901
+ As this is a costly operation, it is recommended to set this parameter to
902
+ False if you are sure that your data does not contain NaNs (or when the
903
+ downsampler can handle NaNs, e.g., EveryNthPoint). This should considerably
904
+ speed up the graph construction time.
891
905
**trace_kwargs: dict
892
906
Additional trace related keyword arguments.
893
907
e.g.: row=.., col=..., secondary_y=...
@@ -959,7 +973,7 @@ def add_trace(
959
973
960
974
# construct the hf_data_container
961
975
# TODO in future version -> maybe regex on kwargs which start with `hf_`
962
- dc = self ._parse_get_trace_props (trace , hf_x , hf_y , hf_text , hf_hovertext )
976
+ dc = self ._parse_get_trace_props (trace , hf_x , hf_y , hf_text , hf_hovertext , check_nans )
963
977
964
978
# These traces will determine the autoscale its RANGE!
965
979
# -> so also store when `limit_to_view` is set.
@@ -1018,6 +1032,7 @@ def add_traces(
1018
1032
| List [AbstractSeriesAggregator ]
1019
1033
| AbstractFigureAggregator = None ,
1020
1034
limit_to_views : List [bool ] | bool = False ,
1035
+ check_nans : List [bool ] | bool = True ,
1021
1036
** traces_kwargs ,
1022
1037
):
1023
1038
"""Add traces to the figure.
@@ -1052,13 +1067,22 @@ def add_traces(
1052
1067
aggregator is passed, all traces will use this aggregator.
1053
1068
If this variable is not set, ``_global_downsampler`` will be used.
1054
1069
limit_to_views : None | List[bool] | bool, optional
1055
- List of limit_to_view booleans for the added traces. If set to True
1056
- the trace's datapoints will be cut to the corresponding front-end view,
1057
- even if the total number of samples is lower than ``max_n_samples``. If a
1058
- single boolean is passed, all to be added traces will use this value,
1070
+ List of limit_to_view booleans for the added traces. If set to True the
1071
+ trace's datapoints will be cut to the corresponding front-end view, even if
1072
+ the total number of samples is lower than ``max_n_samples``.
1073
+ If a single boolean is passed, all to be added traces will use this value,
1059
1074
by default False.\n
1060
1075
Remark that setting this parameter to True ensures that low frequency traces
1061
1076
are added to the ``hf_data`` property.
1077
+ check_nans : None | List[bool] | bool, optional
1078
+ List of check_nans booleans for the added traces. If set to True, the
1079
+ trace's datapoints will be checked for NaNs. If a single boolean is passed,
1080
+ all to be added traces will use this value, by default True.\n
1081
+ As this is a costly operation, it is recommended to set this parameter to
1082
+ False if the data is known to contain no NaNs (or when the downsampler can
1083
+ handle NaNs, e.g., EveryNthPoint). This will considerably speed up the graph
1084
+ construction time.
1085
+
1062
1086
**traces_kwargs: dict
1063
1087
Additional trace related keyword arguments.
1064
1088
e.g.: rows=.., cols=..., secondary_ys=...
@@ -1098,9 +1122,11 @@ def add_traces(
1098
1122
downsamplers = [downsamplers ] * len (data )
1099
1123
if isinstance (limit_to_views , bool ):
1100
1124
limit_to_views = [limit_to_views ] * len (data )
1125
+ if isinstance (check_nans , bool ):
1126
+ check_nans = [check_nans ] * len (data )
1101
1127
1102
- for i , (trace , max_out , downsampler , limit_to_view ) in enumerate (
1103
- zip (data , max_n_samples , downsamplers , limit_to_views )
1128
+ for i , (trace , max_out , downsampler , limit_to_view , check_nan ) in enumerate (
1129
+ zip (data , max_n_samples , downsamplers , limit_to_views , check_nans )
1104
1130
):
1105
1131
if (
1106
1132
trace .type .lower () not in self ._high_frequency_traces
@@ -1112,7 +1138,7 @@ def add_traces(
1112
1138
if not limit_to_view and (trace .y is None or len (trace .y ) <= max_out_s ):
1113
1139
continue
1114
1140
1115
- dc = self ._parse_get_trace_props (trace )
1141
+ dc = self ._parse_get_trace_props (trace , check_nans = check_nan )
1116
1142
self ._hf_data [trace .uid ] = self ._construct_hf_data_dict (
1117
1143
dc ,
1118
1144
trace = trace ,
0 commit comments