validmind 2.5.8__py3-none-any.whl → 2.5.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- validmind/__version__.py +1 -1
- validmind/ai/test_descriptions.py +26 -7
- validmind/api_client.py +89 -43
- validmind/client.py +2 -2
- validmind/client_config.py +11 -14
- validmind/datasets/regression/fred_timeseries.py +67 -138
- validmind/template.py +1 -0
- validmind/test_suites/__init__.py +0 -2
- validmind/test_suites/statsmodels_timeseries.py +1 -1
- validmind/test_suites/summarization.py +0 -1
- validmind/test_suites/time_series.py +0 -43
- validmind/tests/__types__.py +3 -13
- validmind/tests/data_validation/ACFandPACFPlot.py +15 -13
- validmind/tests/data_validation/ADF.py +31 -24
- validmind/tests/data_validation/AutoAR.py +9 -9
- validmind/tests/data_validation/AutoMA.py +23 -16
- validmind/tests/data_validation/AutoSeasonality.py +18 -16
- validmind/tests/data_validation/AutoStationarity.py +21 -16
- validmind/tests/data_validation/BivariateScatterPlots.py +67 -96
- validmind/tests/data_validation/ChiSquaredFeaturesTable.py +82 -124
- validmind/tests/data_validation/ClassImbalance.py +15 -12
- validmind/tests/data_validation/DFGLSArch.py +19 -13
- validmind/tests/data_validation/DatasetDescription.py +17 -11
- validmind/tests/data_validation/DatasetSplit.py +7 -5
- validmind/tests/data_validation/DescriptiveStatistics.py +28 -21
- validmind/tests/data_validation/Duplicates.py +33 -25
- validmind/tests/data_validation/EngleGrangerCoint.py +35 -33
- validmind/tests/data_validation/FeatureTargetCorrelationPlot.py +59 -71
- validmind/tests/data_validation/HighCardinality.py +19 -12
- validmind/tests/data_validation/HighPearsonCorrelation.py +27 -22
- validmind/tests/data_validation/IQROutliersBarPlot.py +13 -10
- validmind/tests/data_validation/IQROutliersTable.py +40 -36
- validmind/tests/data_validation/IsolationForestOutliers.py +21 -14
- validmind/tests/data_validation/KPSS.py +34 -29
- validmind/tests/data_validation/LaggedCorrelationHeatmap.py +22 -15
- validmind/tests/data_validation/MissingValues.py +32 -27
- validmind/tests/data_validation/MissingValuesBarPlot.py +25 -21
- validmind/tests/data_validation/PearsonCorrelationMatrix.py +71 -84
- validmind/tests/data_validation/PhillipsPerronArch.py +37 -30
- validmind/tests/data_validation/RollingStatsPlot.py +31 -23
- validmind/tests/data_validation/ScatterPlot.py +63 -78
- validmind/tests/data_validation/SeasonalDecompose.py +38 -34
- validmind/tests/data_validation/Skewness.py +35 -37
- validmind/tests/data_validation/SpreadPlot.py +35 -35
- validmind/tests/data_validation/TabularCategoricalBarPlots.py +23 -17
- validmind/tests/data_validation/TabularDateTimeHistograms.py +21 -13
- validmind/tests/data_validation/TabularDescriptionTables.py +51 -16
- validmind/tests/data_validation/TabularNumericalHistograms.py +25 -22
- validmind/tests/data_validation/TargetRateBarPlots.py +21 -14
- validmind/tests/data_validation/TimeSeriesDescription.py +25 -18
- validmind/tests/data_validation/TimeSeriesDescriptiveStatistics.py +23 -17
- validmind/tests/data_validation/TimeSeriesFrequency.py +24 -17
- validmind/tests/data_validation/TimeSeriesHistogram.py +33 -32
- validmind/tests/data_validation/TimeSeriesLinePlot.py +17 -10
- validmind/tests/data_validation/TimeSeriesMissingValues.py +15 -10
- validmind/tests/data_validation/TimeSeriesOutliers.py +37 -33
- validmind/tests/data_validation/TooManyZeroValues.py +16 -11
- validmind/tests/data_validation/UniqueRows.py +11 -6
- validmind/tests/data_validation/WOEBinPlots.py +23 -16
- validmind/tests/data_validation/WOEBinTable.py +35 -30
- validmind/tests/data_validation/ZivotAndrewsArch.py +34 -28
- validmind/tests/data_validation/nlp/CommonWords.py +21 -14
- validmind/tests/data_validation/nlp/Hashtags.py +27 -20
- validmind/tests/data_validation/nlp/LanguageDetection.py +33 -14
- validmind/tests/data_validation/nlp/Mentions.py +21 -15
- validmind/tests/data_validation/nlp/PolarityAndSubjectivity.py +32 -9
- validmind/tests/data_validation/nlp/Punctuations.py +24 -20
- validmind/tests/data_validation/nlp/Sentiment.py +27 -8
- validmind/tests/data_validation/nlp/StopWords.py +26 -19
- validmind/tests/data_validation/nlp/TextDescription.py +36 -35
- validmind/tests/data_validation/nlp/Toxicity.py +32 -9
- validmind/tests/decorator.py +81 -42
- validmind/tests/model_validation/BertScore.py +36 -27
- validmind/tests/model_validation/BleuScore.py +25 -19
- validmind/tests/model_validation/ClusterSizeDistribution.py +38 -34
- validmind/tests/model_validation/ContextualRecall.py +35 -13
- validmind/tests/model_validation/FeaturesAUC.py +32 -13
- validmind/tests/model_validation/MeteorScore.py +46 -33
- validmind/tests/model_validation/ModelMetadata.py +32 -64
- validmind/tests/model_validation/ModelPredictionResiduals.py +75 -73
- validmind/tests/model_validation/RegardScore.py +30 -14
- validmind/tests/model_validation/RegressionResidualsPlot.py +10 -5
- validmind/tests/model_validation/RougeScore.py +36 -30
- validmind/tests/model_validation/TimeSeriesPredictionWithCI.py +30 -14
- validmind/tests/model_validation/TimeSeriesPredictionsPlot.py +27 -30
- validmind/tests/model_validation/TimeSeriesR2SquareBySegments.py +68 -63
- validmind/tests/model_validation/TokenDisparity.py +31 -23
- validmind/tests/model_validation/ToxicityScore.py +26 -17
- validmind/tests/model_validation/embeddings/ClusterDistribution.py +24 -20
- validmind/tests/model_validation/embeddings/CosineSimilarityComparison.py +30 -27
- validmind/tests/model_validation/embeddings/CosineSimilarityDistribution.py +7 -5
- validmind/tests/model_validation/embeddings/CosineSimilarityHeatmap.py +32 -23
- validmind/tests/model_validation/embeddings/DescriptiveAnalytics.py +7 -5
- validmind/tests/model_validation/embeddings/EmbeddingsVisualization2D.py +15 -11
- validmind/tests/model_validation/embeddings/EuclideanDistanceComparison.py +29 -29
- validmind/tests/model_validation/embeddings/EuclideanDistanceHeatmap.py +34 -25
- validmind/tests/model_validation/embeddings/PCAComponentsPairwisePlots.py +38 -26
- validmind/tests/model_validation/embeddings/StabilityAnalysis.py +40 -1
- validmind/tests/model_validation/embeddings/StabilityAnalysisKeyword.py +18 -17
- validmind/tests/model_validation/embeddings/StabilityAnalysisRandomNoise.py +40 -45
- validmind/tests/model_validation/embeddings/StabilityAnalysisSynonyms.py +17 -19
- validmind/tests/model_validation/embeddings/StabilityAnalysisTranslation.py +29 -25
- validmind/tests/model_validation/embeddings/TSNEComponentsPairwisePlots.py +38 -28
- validmind/tests/model_validation/ragas/AnswerCorrectness.py +5 -4
- validmind/tests/model_validation/ragas/AnswerRelevance.py +5 -4
- validmind/tests/model_validation/ragas/AnswerSimilarity.py +5 -4
- validmind/tests/model_validation/ragas/AspectCritique.py +7 -0
- validmind/tests/model_validation/ragas/ContextEntityRecall.py +9 -8
- validmind/tests/model_validation/ragas/ContextPrecision.py +5 -4
- validmind/tests/model_validation/ragas/ContextRecall.py +5 -4
- validmind/tests/model_validation/ragas/Faithfulness.py +5 -4
- validmind/tests/model_validation/ragas/utils.py +6 -0
- validmind/tests/model_validation/sklearn/AdjustedMutualInformation.py +19 -12
- validmind/tests/model_validation/sklearn/AdjustedRandIndex.py +22 -17
- validmind/tests/model_validation/sklearn/ClassifierPerformance.py +27 -25
- validmind/tests/model_validation/sklearn/ClusterCosineSimilarity.py +7 -5
- validmind/tests/model_validation/sklearn/ClusterPerformance.py +40 -78
- validmind/tests/model_validation/sklearn/ClusterPerformanceMetrics.py +15 -17
- validmind/tests/model_validation/sklearn/CompletenessScore.py +17 -11
- validmind/tests/model_validation/sklearn/ConfusionMatrix.py +22 -15
- validmind/tests/model_validation/sklearn/FeatureImportance.py +95 -0
- validmind/tests/model_validation/sklearn/FowlkesMallowsScore.py +7 -7
- validmind/tests/model_validation/sklearn/HomogeneityScore.py +19 -12
- validmind/tests/model_validation/sklearn/HyperParametersTuning.py +35 -30
- validmind/tests/model_validation/sklearn/KMeansClustersOptimization.py +10 -5
- validmind/tests/model_validation/sklearn/MinimumAccuracy.py +32 -32
- validmind/tests/model_validation/sklearn/MinimumF1Score.py +23 -23
- validmind/tests/model_validation/sklearn/MinimumROCAUCScore.py +15 -10
- validmind/tests/model_validation/sklearn/ModelsPerformanceComparison.py +26 -19
- validmind/tests/model_validation/sklearn/OverfitDiagnosis.py +38 -18
- validmind/tests/model_validation/sklearn/PermutationFeatureImportance.py +31 -25
- validmind/tests/model_validation/sklearn/PopulationStabilityIndex.py +8 -6
- validmind/tests/model_validation/sklearn/PrecisionRecallCurve.py +24 -17
- validmind/tests/model_validation/sklearn/ROCCurve.py +12 -7
- validmind/tests/model_validation/sklearn/RegressionErrors.py +74 -130
- validmind/tests/model_validation/sklearn/RegressionErrorsComparison.py +27 -12
- validmind/tests/model_validation/sklearn/{RegressionModelsPerformanceComparison.py → RegressionPerformance.py} +18 -20
- validmind/tests/model_validation/sklearn/RegressionR2Square.py +55 -93
- validmind/tests/model_validation/sklearn/RegressionR2SquareComparison.py +32 -13
- validmind/tests/model_validation/sklearn/RobustnessDiagnosis.py +36 -32
- validmind/tests/model_validation/sklearn/SHAPGlobalImportance.py +7 -5
- validmind/tests/model_validation/sklearn/SilhouettePlot.py +27 -19
- validmind/tests/model_validation/sklearn/TrainingTestDegradation.py +25 -18
- validmind/tests/model_validation/sklearn/VMeasure.py +14 -13
- validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py +7 -5
- validmind/tests/model_validation/statsmodels/AutoARIMA.py +24 -18
- validmind/tests/model_validation/statsmodels/BoxPierce.py +14 -10
- validmind/tests/model_validation/statsmodels/CumulativePredictionProbabilities.py +73 -104
- validmind/tests/model_validation/statsmodels/DurbinWatsonTest.py +19 -12
- validmind/tests/model_validation/statsmodels/GINITable.py +44 -77
- validmind/tests/model_validation/statsmodels/JarqueBera.py +27 -22
- validmind/tests/model_validation/statsmodels/KolmogorovSmirnov.py +33 -34
- validmind/tests/model_validation/statsmodels/LJungBox.py +32 -28
- validmind/tests/model_validation/statsmodels/Lilliefors.py +27 -24
- validmind/tests/model_validation/statsmodels/PredictionProbabilitiesHistogram.py +87 -119
- validmind/tests/model_validation/statsmodels/RegressionCoeffs.py +100 -0
- validmind/tests/model_validation/statsmodels/RegressionFeatureSignificance.py +14 -9
- validmind/tests/model_validation/statsmodels/RegressionModelForecastPlot.py +17 -13
- validmind/tests/model_validation/statsmodels/RegressionModelForecastPlotLevels.py +46 -43
- validmind/tests/model_validation/statsmodels/RegressionModelSensitivityPlot.py +38 -36
- validmind/tests/model_validation/statsmodels/RegressionModelSummary.py +30 -28
- validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImportance.py +18 -11
- validmind/tests/model_validation/statsmodels/RunsTest.py +32 -28
- validmind/tests/model_validation/statsmodels/ScorecardHistogram.py +75 -107
- validmind/tests/model_validation/statsmodels/ShapiroWilk.py +15 -8
- validmind/tests/ongoing_monitoring/FeatureDrift.py +10 -6
- validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py +31 -25
- validmind/tests/ongoing_monitoring/PredictionCorrelation.py +29 -21
- validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +31 -23
- validmind/tests/prompt_validation/Bias.py +14 -11
- validmind/tests/prompt_validation/Clarity.py +16 -14
- validmind/tests/prompt_validation/Conciseness.py +7 -5
- validmind/tests/prompt_validation/Delimitation.py +23 -22
- validmind/tests/prompt_validation/NegativeInstruction.py +7 -5
- validmind/tests/prompt_validation/Robustness.py +12 -10
- validmind/tests/prompt_validation/Specificity.py +13 -11
- validmind/tests/prompt_validation/ai_powered_test.py +6 -0
- validmind/tests/run.py +68 -23
- validmind/unit_metrics/__init__.py +81 -144
- validmind/unit_metrics/classification/{sklearn/Accuracy.py → Accuracy.py} +1 -1
- validmind/unit_metrics/classification/{sklearn/F1.py → F1.py} +1 -1
- validmind/unit_metrics/classification/{sklearn/Precision.py → Precision.py} +1 -1
- validmind/unit_metrics/classification/{sklearn/ROC_AUC.py → ROC_AUC.py} +1 -2
- validmind/unit_metrics/classification/{sklearn/Recall.py → Recall.py} +1 -1
- validmind/unit_metrics/regression/{sklearn/AdjustedRSquaredScore.py → AdjustedRSquaredScore.py} +1 -1
- validmind/unit_metrics/regression/GiniCoefficient.py +1 -1
- validmind/unit_metrics/regression/HuberLoss.py +1 -1
- validmind/unit_metrics/regression/KolmogorovSmirnovStatistic.py +1 -1
- validmind/unit_metrics/regression/{sklearn/MeanAbsoluteError.py → MeanAbsoluteError.py} +1 -1
- validmind/unit_metrics/regression/MeanAbsolutePercentageError.py +1 -1
- validmind/unit_metrics/regression/MeanBiasDeviation.py +1 -1
- validmind/unit_metrics/regression/{sklearn/MeanSquaredError.py → MeanSquaredError.py} +1 -1
- validmind/unit_metrics/regression/QuantileLoss.py +1 -1
- validmind/unit_metrics/regression/{sklearn/RSquaredScore.py → RSquaredScore.py} +1 -1
- validmind/unit_metrics/regression/{sklearn/RootMeanSquaredError.py → RootMeanSquaredError.py} +1 -1
- validmind/vm_models/dataset/dataset.py +2 -0
- validmind/vm_models/figure.py +5 -0
- validmind/vm_models/test/result_wrapper.py +93 -132
- {validmind-2.5.8.dist-info → validmind-2.5.15.dist-info}/METADATA +1 -1
- {validmind-2.5.8.dist-info → validmind-2.5.15.dist-info}/RECORD +203 -210
- validmind/tests/data_validation/ANOVAOneWayTable.py +0 -138
- validmind/tests/data_validation/BivariateFeaturesBarPlots.py +0 -142
- validmind/tests/data_validation/BivariateHistograms.py +0 -117
- validmind/tests/data_validation/HeatmapFeatureCorrelations.py +0 -124
- validmind/tests/data_validation/MissingValuesRisk.py +0 -88
- validmind/tests/model_validation/ModelMetadataComparison.py +0 -59
- validmind/tests/model_validation/sklearn/FeatureImportanceComparison.py +0 -83
- validmind/tests/model_validation/statsmodels/RegressionCoeffsPlot.py +0 -135
- validmind/tests/model_validation/statsmodels/RegressionModelsCoeffs.py +0 -103
- {validmind-2.5.8.dist-info → validmind-2.5.15.dist-info}/LICENSE +0 -0
- {validmind-2.5.8.dist-info → validmind-2.5.15.dist-info}/WHEEL +0 -0
- {validmind-2.5.8.dist-info → validmind-2.5.15.dist-info}/entry_points.txt +0 -0
@@ -63,19 +63,63 @@ async def update_metadata(content_id: str, text: str, _json: Union[Dict, List] =
|
|
63
63
|
|
64
64
|
|
65
65
|
def plot_figures(figures: List[Figure]) -> None:
|
66
|
-
"""
|
67
|
-
Plot figures to a ipywidgets GridBox
|
68
|
-
"""
|
69
|
-
|
66
|
+
"""Plot figures to a ipywidgets GridBox"""
|
70
67
|
plots = [figure.to_widget() for figure in figures]
|
71
|
-
|
72
68
|
num_columns = 2 if len(figures) > 1 else 1
|
69
|
+
|
73
70
|
return GridBox(
|
74
71
|
plots,
|
75
72
|
layout=Layout(grid_template_columns=f"repeat({num_columns}, 1fr)"),
|
76
73
|
)
|
77
74
|
|
78
75
|
|
76
|
+
def _summary_tables_to_widget(summary: ResultSummary):
|
77
|
+
"""Convert summary (list of json tables) into ipywidgets"""
|
78
|
+
widgets = []
|
79
|
+
|
80
|
+
for table in summary.results:
|
81
|
+
if table.metadata and table.metadata.title:
|
82
|
+
widgets.append(HTML(f"<h4>{table.metadata.title}</h4>"))
|
83
|
+
|
84
|
+
df_html = (
|
85
|
+
pd.DataFrame(table.data)
|
86
|
+
.style.format(precision=4)
|
87
|
+
.hide(axis="index")
|
88
|
+
.set_table_styles(
|
89
|
+
[
|
90
|
+
{
|
91
|
+
"selector": "",
|
92
|
+
"props": [("width", "100%")],
|
93
|
+
},
|
94
|
+
{
|
95
|
+
"selector": "th",
|
96
|
+
"props": [("text-align", "left")],
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"selector": "tbody tr:nth-child(even)",
|
100
|
+
"props": [("background-color", "#FFFFFF")],
|
101
|
+
},
|
102
|
+
{
|
103
|
+
"selector": "tbody tr:nth-child(odd)",
|
104
|
+
"props": [("background-color", "#F5F5F5")],
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"selector": "td, th",
|
108
|
+
"props": [
|
109
|
+
("padding-left", "5px"),
|
110
|
+
("padding-right", "5px"),
|
111
|
+
],
|
112
|
+
},
|
113
|
+
]
|
114
|
+
)
|
115
|
+
.set_properties(**{"text-align": "left"})
|
116
|
+
.to_html(escape=False)
|
117
|
+
)
|
118
|
+
widgets.append(HTML(df_html))
|
119
|
+
|
120
|
+
return widgets
|
121
|
+
|
122
|
+
|
79
123
|
@dataclass
|
80
124
|
class ResultWrapper(ABC):
|
81
125
|
"""Base Class for test suite results"""
|
@@ -105,53 +149,6 @@ class ResultWrapper(ABC):
|
|
105
149
|
|
106
150
|
return self.to_widget()
|
107
151
|
|
108
|
-
def _summary_tables_to_widget(self, summary: ResultSummary):
|
109
|
-
"""
|
110
|
-
Create an ipywdiget representation of the summary tables
|
111
|
-
"""
|
112
|
-
tables = []
|
113
|
-
for table in summary.results:
|
114
|
-
# Explore advanced styling
|
115
|
-
summary_table = (
|
116
|
-
pd.DataFrame(table.data)
|
117
|
-
.style.format(precision=4)
|
118
|
-
.hide(axis="index")
|
119
|
-
.set_table_styles(
|
120
|
-
[
|
121
|
-
{
|
122
|
-
"selector": "",
|
123
|
-
"props": [("width", "100%")],
|
124
|
-
},
|
125
|
-
{
|
126
|
-
"selector": "th",
|
127
|
-
"props": [("text-align", "left")],
|
128
|
-
},
|
129
|
-
{
|
130
|
-
"selector": "tbody tr:nth-child(even)",
|
131
|
-
"props": [("background-color", "#FFFFFF")],
|
132
|
-
},
|
133
|
-
{
|
134
|
-
"selector": "tbody tr:nth-child(odd)",
|
135
|
-
"props": [("background-color", "#F5F5F5")],
|
136
|
-
},
|
137
|
-
{
|
138
|
-
"selector": "td, th",
|
139
|
-
"props": [
|
140
|
-
("padding-left", "5px"),
|
141
|
-
("padding-right", "5px"),
|
142
|
-
],
|
143
|
-
},
|
144
|
-
]
|
145
|
-
)
|
146
|
-
.set_properties(**{"text-align": "left"})
|
147
|
-
.to_html(escape=False)
|
148
|
-
) # table.data is an orient=records dump
|
149
|
-
|
150
|
-
if table.metadata and table.metadata.title:
|
151
|
-
tables.append(HTML(value=f"<h3>{table.metadata.title}</h3>"))
|
152
|
-
tables.append(HTML(value=summary_table))
|
153
|
-
return tables
|
154
|
-
|
155
152
|
def _validate_section_id_for_block(self, section_id: str, position: int = None):
|
156
153
|
"""
|
157
154
|
Validate the section_id exits on the template before logging. We validate
|
@@ -244,9 +241,11 @@ class MetricResultWrapper(ResultWrapper):
|
|
244
241
|
"""
|
245
242
|
|
246
243
|
name: str = "Metric"
|
247
|
-
|
244
|
+
scalar: Optional[Union[int, float]] = None
|
248
245
|
metric: Optional[MetricResult] = None
|
249
|
-
|
246
|
+
figures: Optional[List[Figure]] = None
|
247
|
+
inputs: List[str] = None # List of input ids
|
248
|
+
params: Dict = None
|
250
249
|
|
251
250
|
def __repr__(self) -> str:
|
252
251
|
if self.metric:
|
@@ -254,18 +253,12 @@ class MetricResultWrapper(ResultWrapper):
|
|
254
253
|
else:
|
255
254
|
return f'{self.__class__.__name__}(result_id="{self.result_id}", figures)'
|
256
255
|
|
257
|
-
def __str__(self) -> str:
|
258
|
-
if self.metric:
|
259
|
-
return f'{self.__class__.__name__}(result_id="{self.result_id}", metric, figures)'
|
260
|
-
else:
|
261
|
-
return f"{self.__class__.__name__}(result_id={self.result_id}, figures)"
|
262
|
-
|
263
256
|
def to_widget(self):
|
264
257
|
if self.metric and self.metric.key == "dataset_description":
|
265
258
|
return ""
|
266
259
|
|
267
260
|
vbox_children = [
|
268
|
-
HTML(
|
261
|
+
HTML(f"<h1>{test_id_to_name(self.result_id)}</h1>"),
|
269
262
|
]
|
270
263
|
|
271
264
|
if self.result_metadata:
|
@@ -274,70 +267,36 @@ class MetricResultWrapper(ResultWrapper):
|
|
274
267
|
metric_description = metric_description.get_description()
|
275
268
|
self.result_metadata[0]["text"] = metric_description
|
276
269
|
|
277
|
-
vbox_children.append(HTML(
|
270
|
+
vbox_children.append(HTML(metric_description))
|
271
|
+
|
272
|
+
if self.scalar is not None:
|
273
|
+
vbox_children.append(
|
274
|
+
HTML(
|
275
|
+
"<h3>Unit Metrics</h3>"
|
276
|
+
f"<p>{test_id_to_name(self.result_id)} "
|
277
|
+
f"(<i>{self.result_id}</i>): "
|
278
|
+
f"<code>{self.scalar}</code></p>"
|
279
|
+
)
|
280
|
+
)
|
278
281
|
|
279
282
|
if self.metric:
|
283
|
+
vbox_children.append(HTML("<h3>Tables</h3>"))
|
280
284
|
if self.output_template:
|
281
|
-
|
282
|
-
|
285
|
+
vbox_children.append(
|
286
|
+
HTML(
|
287
|
+
OutputTemplate(self.output_template).render(
|
288
|
+
value=self.metric.value
|
289
|
+
)
|
290
|
+
)
|
283
291
|
)
|
284
|
-
vbox_children.append(HTML(rendered_output))
|
285
292
|
elif self.metric.summary:
|
286
|
-
|
287
|
-
vbox_children.extend(tables)
|
293
|
+
vbox_children.extend(_summary_tables_to_widget(self.metric.summary))
|
288
294
|
|
289
295
|
if self.figures:
|
290
|
-
vbox_children.append(HTML(
|
296
|
+
vbox_children.append(HTML("<h3>Plots</h3>"))
|
291
297
|
plot_widgets = plot_figures(self.figures)
|
292
298
|
vbox_children.append(plot_widgets)
|
293
299
|
|
294
|
-
vbox_children.append(
|
295
|
-
HTML(
|
296
|
-
value="""
|
297
|
-
<style>
|
298
|
-
.metric-result {
|
299
|
-
background-color: #F5F5F5;
|
300
|
-
border: 1px solid #e0e0e0;
|
301
|
-
border-radius: 4px;
|
302
|
-
padding: 10px;
|
303
|
-
margin: 10px 0;
|
304
|
-
}
|
305
|
-
.metric-result-body {
|
306
|
-
display: flex;
|
307
|
-
flex-direction: column;
|
308
|
-
justify-content: space-between;
|
309
|
-
gap: 10px;
|
310
|
-
}
|
311
|
-
.metric-body-column {
|
312
|
-
display: flex;
|
313
|
-
flex-direction: column;
|
314
|
-
justify-content: space-between;
|
315
|
-
width: 33%;
|
316
|
-
}
|
317
|
-
.metric-body-column-title {
|
318
|
-
font-size: 16px;
|
319
|
-
font-weight: 600;
|
320
|
-
}
|
321
|
-
.metric-value {
|
322
|
-
display: flex;
|
323
|
-
flex-direction: column;
|
324
|
-
justify-content: space-between;
|
325
|
-
margin-top: 15px;
|
326
|
-
}
|
327
|
-
.metric-value-title {
|
328
|
-
font-size: 16px;
|
329
|
-
font-weight: 600;
|
330
|
-
}
|
331
|
-
.metric-value-value {
|
332
|
-
font-size: 14px;
|
333
|
-
font-weight: 500;
|
334
|
-
margin-top: 10px;
|
335
|
-
}
|
336
|
-
</style>
|
337
|
-
"""
|
338
|
-
)
|
339
|
-
)
|
340
|
-
|
341
300
|
return VBox(vbox_children)
|
342
301
|
|
343
302
|
def _get_filtered_summary(self):
|
@@ -379,6 +338,17 @@ class MetricResultWrapper(ResultWrapper):
|
|
379
338
|
):
|
380
339
|
tasks = [] # collect tasks to run in parallel (async)
|
381
340
|
|
341
|
+
if self.scalar is not None:
|
342
|
+
# scalars (unit metrics) are logged as key-value pairs associated with the inventory model
|
343
|
+
tasks.append(
|
344
|
+
api_client.alog_metric(
|
345
|
+
key=self.result_id,
|
346
|
+
value=self.scalar,
|
347
|
+
inputs=self.inputs,
|
348
|
+
params=self.params,
|
349
|
+
)
|
350
|
+
)
|
351
|
+
|
382
352
|
if self.metric:
|
383
353
|
if self.metric.summary and not unsafe:
|
384
354
|
self.metric.summary = self._get_filtered_summary()
|
@@ -411,7 +381,7 @@ class MetricResultWrapper(ResultWrapper):
|
|
411
381
|
)
|
412
382
|
)
|
413
383
|
|
414
|
-
await asyncio.gather(*tasks)
|
384
|
+
return await asyncio.gather(*tasks)
|
415
385
|
|
416
386
|
|
417
387
|
@dataclass
|
@@ -433,24 +403,13 @@ class ThresholdTestResultWrapper(ResultWrapper):
|
|
433
403
|
else:
|
434
404
|
return f'{self.__class__.__name__}(result_id="{self.result_id}", figures)'
|
435
405
|
|
436
|
-
def __str__(self) -> str:
|
437
|
-
if self.test_results:
|
438
|
-
return (
|
439
|
-
f'{self.__class__.__name__}(result_id="{self.result_id}", test_results)'
|
440
|
-
)
|
441
|
-
else:
|
442
|
-
return f'{self.__class__.__name__}(result_id="{self.result_id}", figures)'
|
443
|
-
|
444
406
|
def to_widget(self):
|
445
407
|
vbox_children = []
|
446
408
|
description_html = []
|
447
409
|
|
448
|
-
test_params = json.dumps(self.test_results.params, cls=NumpyEncoder, indent=2)
|
449
|
-
|
450
|
-
test_title = test_id_to_name(self.test_results.test_name)
|
451
410
|
description_html.append(
|
452
411
|
f"""
|
453
|
-
<h1>{
|
412
|
+
<h1>{test_id_to_name(self.test_results.test_name)} {"✅" if self.test_results.passed else "❌"}</h1>
|
454
413
|
"""
|
455
414
|
)
|
456
415
|
|
@@ -462,6 +421,7 @@ class ThresholdTestResultWrapper(ResultWrapper):
|
|
462
421
|
|
463
422
|
description_html.append(metric_description)
|
464
423
|
|
424
|
+
test_params = json.dumps(self.test_results.params, cls=NumpyEncoder, indent=2)
|
465
425
|
description_html.append(
|
466
426
|
f"""
|
467
427
|
<h4>Test Parameters</h4>
|
@@ -469,14 +429,14 @@ class ThresholdTestResultWrapper(ResultWrapper):
|
|
469
429
|
"""
|
470
430
|
)
|
471
431
|
|
472
|
-
vbox_children.append(HTML(
|
432
|
+
vbox_children.append(HTML("".join(description_html)))
|
473
433
|
|
474
434
|
if self.test_results.summary:
|
475
|
-
|
476
|
-
vbox_children.extend(
|
435
|
+
vbox_children.append(HTML("<h3>Tables</h3>"))
|
436
|
+
vbox_children.extend(_summary_tables_to_widget(self.test_results.summary))
|
477
437
|
|
478
438
|
if self.figures:
|
479
|
-
vbox_children.append(HTML(
|
439
|
+
vbox_children.append(HTML("<h3>Plots</h3>"))
|
480
440
|
plot_widgets = plot_figures(self.figures)
|
481
441
|
vbox_children.append(plot_widgets)
|
482
442
|
|
@@ -491,6 +451,7 @@ class ThresholdTestResultWrapper(ResultWrapper):
|
|
491
451
|
|
492
452
|
if self.figures:
|
493
453
|
tasks.append(api_client.log_figures(self.figures))
|
454
|
+
|
494
455
|
if hasattr(self, "result_metadata") and self.result_metadata:
|
495
456
|
description = self.result_metadata[0].get("text", "")
|
496
457
|
if isinstance(description, DescriptionFuture):
|