Skip to content

Commit

Permalink
Merge branch 'microsoft:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
karlotimmerman authored Jan 13, 2023
2 parents 2220b16 + 080e8f8 commit 56401de
Show file tree
Hide file tree
Showing 24 changed files with 1,351 additions and 91 deletions.
27 changes: 18 additions & 9 deletions apps/widget/src/app/ModelAssessment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
ICausalAnalysisData,
IErrorAnalysisMatrix,
IHighchartBoxData,
IHighchartBubbleSDKData
IHighchartBubbleSDKClusterData,
ICounterfactualData
} from "@responsible-ai/core-ui";
import {
ModelAssessmentDashboard,
Expand Down Expand Up @@ -168,21 +169,29 @@ export class ModelAssessment extends React.Component<IModelAssessmentProps> {
);
};
callBack.requestBubblePlotData = async (
data: any
): Promise<IHighchartBubbleSDKData> => {
filter: unknown[],
compositeFilter: unknown[],
xAxis: string,
yAxis: string,
abortSignal: AbortSignal
): Promise<IHighchartBubbleSDKClusterData> => {
return callFlaskService(
this.props.config,
data,
"/dataset_analysis_bubble_chart_plot"
[filter, compositeFilter, xAxis, yAxis],
"/dataset_analysis_bubble_chart_plot",
abortSignal
);
};
callBack.requestLocalCounterfactuals = async (
data: any
): Promise<any> => {
counterfactualsId: string,
absoluteIndex: number,
abortSignal: AbortSignal
): Promise<ICounterfactualData> => {
return callFlaskService(
this.props.config,
data,
"/local_counterfactuals"
[counterfactualsId, absoluteIndex],
"/local_counterfactuals",
abortSignal
);
};
callBack.requestMetrics = async (
Expand Down
14 changes: 9 additions & 5 deletions libs/core-ui/src/lib/Context/ModelAssessmentContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { IDataset } from "../Interfaces/IDataset";
import { IErrorAnalysisData } from "../Interfaces/IErrorAnalysisData";
import { IExplanationModelMetadata } from "../Interfaces/IExplanationContext";
import { IHighchartBoxData } from "../Interfaces/IHighchartBoxData";
import { IHighchartBubbleSDKData } from "../Interfaces/IHighchartBubbleData";
import { IHighchartBubbleSDKClusterData } from "../Interfaces/IHighchartBubbleData";
import { IModelExplanationData } from "../Interfaces/IModelExplanationData";
import { ITelemetryEvent } from "../util/ITelemetryEvent";
import { JointDataset } from "../util/JointDataset";
Expand Down Expand Up @@ -61,13 +61,17 @@ export interface IModelAssessmentContext {
abortSignal: AbortSignal
) => Promise<IHighchartBoxData>;
requestBubblePlotData?: (
request: any,
filter: unknown[],
compositeFilter: unknown[],
xAxis: string,
yAxis: string,
abortSignal: AbortSignal
) => Promise<IHighchartBubbleSDKData>;
) => Promise<IHighchartBubbleSDKClusterData>;
requestLocalCounterfactuals?: (
request: any,
counterfactualsId: string,
absoluteIndex: number,
abortSignal: AbortSignal
) => Promise<any>;
) => Promise<ICounterfactualData>;
requestGlobalCausalEffects?: (
id: string,
filter: unknown[],
Expand Down
7 changes: 7 additions & 0 deletions libs/core-ui/src/lib/Interfaces/IHighchartBubbleData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export interface IHighchartBubbleSDKData {
index_series: number[];
x_series: any[];
y_series: any[];
test_data: any[];
}

export interface IHighchartBubbleSDKClusterData {
clusters: IHighchartBubbleSDKData[];
error?: unknown;
}

// Below interface is used by UI to render highchart data. size sent by sdk is used as z to decide the size of the bubble. Since name is sent as null by sdk, it is made optional on UI side and is not used for now in plot data.
Expand All @@ -22,4 +28,5 @@ export interface IHighchartBubbleData {
indexSeries: number[];
xSeries: any[];
ySeries: any[];
testData: any[];
}
1 change: 1 addition & 0 deletions libs/core-ui/src/lib/util/JointDataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
//
export class JointDataset {
public static readonly IndexLabel = "Index";
public static readonly AbsoluteIndexLabel = "AbsoluteIndex";
public static readonly DataLabelRoot = "Data";
public static readonly PredictedYLabel = "PredictedY";
public static readonly ProbabilityYRoot = "ProbabilityClass";
Expand Down
19 changes: 19 additions & 0 deletions libs/counterfactuals/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": [
"**/getBubbleChartOptions.ts",
"**/CounterfactualComponent.tsx",
"**/LargeCounterfactualChart.tsx"
],
"rules": {
"dot-notation": "off"
}
},
{
"files": [
"**/CounterfactualComponent.tsx",
"**/LargeCounterfactualChart.tsx"
],
"rules": {
"max-lines": "off"
}
}
]
}
5 changes: 4 additions & 1 deletion libs/counterfactuals/src/lib/CounterfactualChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export interface ICounterfactualChartProps {
index?: number,
value?: string
) => void;
setTemporaryPointToCopyOfDatasetPoint: (index: number) => void;
setTemporaryPointToCopyOfDatasetPoint: (
index: number,
absoluteIndex?: number
) => void;
telemetryHook?: (message: ITelemetryEvent) => void;
togglePanel: () => void;
toggleSelectionOfPoint: (index?: number) => void;
Expand Down
73 changes: 53 additions & 20 deletions libs/counterfactuals/src/lib/CounterfactualChartLegend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
Stack
} from "@fluentui/react";
import {
JointDataset,
defaultModelAssessmentContext,
ModelAssessmentContext,
FluentUIStyles,
Expand All @@ -18,7 +17,9 @@ import {
ITelemetryEvent,
TelemetryLevels,
TelemetryEventName,
DatasetTaskType
DatasetTaskType,
ifEnableLargeData,
JointDataset
} from "@responsible-ai/core-ui";
import { WhatIfConstants } from "@responsible-ai/interpret";
import { localization } from "@responsible-ai/localization";
Expand All @@ -35,8 +36,14 @@ export interface ICounterfactualChartLegendProps {
}>;
data: ICounterfactualData;
selectedPointsIndexes: number[];
indexSeries: number[];
isCounterfactualsDataLoading?: boolean;
removeCustomPoint: (index: number) => void;
setTemporaryPointToCopyOfDatasetPoint: (index: number) => void;
setTemporaryPointToCopyOfDatasetPoint: (
index: number,
absoluteIndex?: number
) => void;
setCounterfactualData?: (absoluteIndex?: number) => Promise<void>;
telemetryHook?: (message: ITelemetryEvent) => void;
toggleCustomActivation: (index: number) => void;
togglePanel: () => void;
Expand All @@ -52,23 +59,26 @@ export class CounterfactualChartLegend extends React.PureComponent<ICounterfactu
const classNames = counterfactualChartStyles();
return (
<Stack className={classNames.legendAndText}>
<ComboBox
id={"CounterfactualSelectedDatapoint"}
className={classNames.legendLabel}
label={localization.Counterfactuals.selectedDatapoint}
onChange={this.selectPointFromDropdown}
options={this.getDataOptions()}
selectedKey={`${this.props.selectedPointsIndexes[0]}`}
ariaLabel={"datapoint picker"}
useComboBoxAsMenuWidth
styles={FluentUIStyles.smallDropdownStyle}
/>
{this.displayDatapointDropbox() && (
<ComboBox
id={"CounterfactualSelectedDatapoint"}
className={classNames.legendLabel}
label={localization.Counterfactuals.selectedDatapoint}
onChange={this.selectPointFromDropdown}
options={this.getDataOptions()}
selectedKey={`${this.props.selectedPointsIndexes[0]}`}
ariaLabel={"datapoint picker"}
useComboBoxAsMenuWidth
styles={FluentUIStyles.smallDropdownStyle}
disabled={this.props.isCounterfactualsDataLoading}
/>
)}
<div className={classNames.legendLabel}>
<b>{`${this.getTargetDescription()}: `}</b>
{getCurrentLabel(
this.context.dataset.task_type,
this.props.data.desired_range,
this.props.data.desired_class
this.props.data?.desired_range,
this.props.data?.desired_class
)}
</div>
<PrimaryButton
Expand Down Expand Up @@ -109,14 +119,29 @@ export class CounterfactualChartLegend extends React.PureComponent<ICounterfactu
return localization.Counterfactuals.currentClass;
}

private displayDatapointDropbox(): boolean {
const isLargeDataEnabled = ifEnableLargeData(this.context.dataset);
if (!isLargeDataEnabled) {
return true;
}

return isLargeDataEnabled && this.props.indexSeries.length > 0;
}

private selectPointFromDropdown = (
_event: React.FormEvent<IComboBox>,
item?: IComboBoxOption
): void => {
if (typeof item?.key === "string") {
const index = Number.parseInt(item.key);
this.props.setTemporaryPointToCopyOfDatasetPoint(index);
this.props.setTemporaryPointToCopyOfDatasetPoint(index, item.data.index);
this.props.toggleSelectionOfPoint(index);
if (
ifEnableLargeData(this.context.dataset) &&
this.props.setCounterfactualData
) {
this.props.setCounterfactualData(item.data.index);
}
this.logTelemetryEvent(
TelemetryEventName.CounterfactualNewDatapointSelectedFromDropdown
);
Expand All @@ -126,17 +151,25 @@ export class CounterfactualChartLegend extends React.PureComponent<ICounterfactu
private disableCounterfactualPanel = (): boolean => {
return (
this.props.selectedPointsIndexes[0] === undefined ||
!this.props.data.cfs_list[this.props.selectedPointsIndexes[0]]
!this.props.data.cfs_list[this.props.selectedPointsIndexes[0]] ||
!!this.props.isCounterfactualsDataLoading
);
};

private getDataOptions(): IComboBoxOption[] {
const indexes = this.context.selectedErrorCohort.cohort.unwrap(
let indexes = this.context.selectedErrorCohort.cohort.unwrap(
JointDataset.IndexLabel
);
indexes.sort((a, b) => Number.parseInt(a) - Number.parseInt(b));
return indexes.map((index) => {
const isLargeDataEnabled = ifEnableLargeData(this.context.dataset);
if (isLargeDataEnabled) {
indexes = this.props.indexSeries;
}

return indexes.map((ind, i) => {
const index = isLargeDataEnabled ? i : ind;
return {
data: { index: indexes[i] },
key: `${index}`,
text: `Index ${index}`
};
Expand Down
Loading

0 comments on commit 56401de

Please sign in to comment.