Skip to content

Commit 985535f

Browse files
shrutipatel31facebook-github-bot
authored andcommitted
Add encoder/decoder support for NotApplicableAnalysisCard
Summary: Add SQA storage support for the new NotApplicableAnalysisCard class: - encoder.py: Add NotApplicableAnalysisCard check with blob_annotation='not_applicable' - decoder.py: Add decoding logic for blob_annotation='not_applicable' - test_sqa_store.py: Add round-trip persistence test This allows NotApplicableAnalysisCard instances to be saved and loaded from the database correctly. Differential Revision: D96248247
1 parent 6142a35 commit 985535f

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

ax/storage/sqa_store/decoder.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
AnalysisCardBase,
2424
AnalysisCardGroup,
2525
ErrorAnalysisCard,
26+
NotApplicableAnalysisCard,
2627
)
2728
from ax.core.arm import Arm
2829
from ax.core.auxiliary import AuxiliaryExperiment, AuxiliaryExperimentPurpose
@@ -1072,6 +1073,15 @@ def analysis_card_from_sqa(
10721073
blob = none_throws(analysis_card_sqa.blob)
10731074
blob_annotation = analysis_card_sqa.blob_annotation
10741075

1076+
if blob_annotation == "not_applicable":
1077+
return NotApplicableAnalysisCard(
1078+
name=analysis_card_sqa.name,
1079+
title=title,
1080+
subtitle=subtitle,
1081+
df=read_json(StringIO(analysis_card_sqa.dataframe_json)),
1082+
blob=blob,
1083+
timestamp=analysis_card_sqa.timestamp,
1084+
)
10751085
if blob_annotation == "error":
10761086
return ErrorAnalysisCard(
10771087
name=analysis_card_sqa.name,

ax/storage/sqa_store/encoder.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
AnalysisCardBase,
2020
AnalysisCardGroup,
2121
ErrorAnalysisCard,
22+
NotApplicableAnalysisCard,
2223
)
2324
from ax.core.arm import Arm
2425
from ax.core.auxiliary import AuxiliaryExperiment, AuxiliaryExperimentPurpose
@@ -1163,7 +1164,9 @@ def analysis_card_to_sqa(
11631164

11641165
card = assert_is_instance(analysis_card, AnalysisCard)
11651166

1166-
if isinstance(card, ErrorAnalysisCard):
1167+
if isinstance(card, NotApplicableAnalysisCard):
1168+
blob_annotation = "not_applicable"
1169+
elif isinstance(card, ErrorAnalysisCard):
11671170
blob_annotation = "error"
11681171
elif isinstance(card, PlotlyAnalysisCard):
11691172
blob_annotation = "plotly"

ax/storage/sqa_store/sqa_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from enum import Enum
1212
from typing import Any, cast
1313

14-
from ax.analysis.analysis import AnalysisCard
14+
from ax.core.analysis_card import AnalysisCard
1515
from ax.core.arm import Arm
1616
from ax.core.auxiliary import AuxiliaryExperiment, AuxiliaryExperimentPurpose
1717
from ax.core.batch_trial import AbandonedArm

ax/storage/sqa_store/tests/test_sqa_store.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
choose_generation_strategy,
2525
GenerationStrategyDispatchStruct,
2626
)
27-
from ax.core.analysis_card import AnalysisCard, AnalysisCardGroup
27+
from ax.core.analysis_card import (
28+
AnalysisCard,
29+
AnalysisCardGroup,
30+
NotApplicableAnalysisCard,
31+
)
2832
from ax.core.arm import Arm
2933
from ax.core.auxiliary import (
3034
AuxiliaryExperiment,
@@ -3067,6 +3071,45 @@ def test_analysis_card(self) -> None:
30673071
self.assertEqual(loaded_small_group_plotly.name, plotly_analysis_card.name)
30683072
self.assertEqual(loaded_small_group_plotly.blob, plotly_analysis_card.blob)
30693073

3074+
def test_not_applicable_analysis_card(self) -> None:
3075+
"""Test that NotApplicableAnalysisCard persists through SQA round-trip."""
3076+
test_df = pd.DataFrame(
3077+
columns=["a", "b"],
3078+
data=[
3079+
[1, 2],
3080+
[3, 4],
3081+
],
3082+
)
3083+
3084+
not_applicable_card = NotApplicableAnalysisCard(
3085+
name="test_not_applicable_analysis_card",
3086+
title="TestAnalysis -- Not Available Yet",
3087+
subtitle="Experiment has no data.",
3088+
df=test_df,
3089+
blob="Waiting for experiment data.",
3090+
)
3091+
3092+
save_experiment(self.experiment)
3093+
3094+
save_analysis_card(
3095+
not_applicable_card,
3096+
self.experiment,
3097+
)
3098+
3099+
loaded_analysis_cards = load_analysis_cards_by_experiment_name(
3100+
self.experiment.name
3101+
)
3102+
3103+
self.assertEqual(len(loaded_analysis_cards), 1)
3104+
loaded_card = assert_is_instance(
3105+
loaded_analysis_cards[0], NotApplicableAnalysisCard
3106+
)
3107+
self.assertEqual(loaded_card.name, not_applicable_card.name)
3108+
self.assertEqual(loaded_card.title, not_applicable_card.title)
3109+
self.assertEqual(loaded_card.subtitle, not_applicable_card.subtitle)
3110+
self.assertEqual(loaded_card.blob, not_applicable_card.blob)
3111+
self.assertTrue(loaded_card.df.equals(not_applicable_card.df))
3112+
30703113
def test_delete_generation_strategy(self) -> None:
30713114
# GIVEN an experiment with a generation strategy
30723115
experiment = get_branin_experiment()

0 commit comments

Comments
 (0)