# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
# ---

# <img src="https://github.com/pmservice/ai-openscale-tutorials/raw/master/notebooks/images/banner.png" align="left" alt="banner">

# # IBM Watson OpenScale and Batch Processing:<br>Apache Spark on Cloud Pak for Data with IBM Analytics Engine

# This notebook must be run in the Python 3.x runtime environment. It requires Watson OpenScale service credentials.
#
# The notebook configures Watson OpenScale to monitor the German Credit Risk model. Use the notebook to enable quality, drift, fairness and explainability monitoring and run on-demand evaluations. Before you can run the notebook, you must have the following resources:
#
# 1. The common configuration JSON, Drift Configuration and Perturbations archives generated by using the [common configuration notebook](https://github.com/IBM/watson-openscale-samples/blob/main/Cloud%20Pak%20for%20Data/Batch%20Support/Configuration%20generation%20for%20OpenScale%20batch%20subscription.ipynb).
# 2. Feedback, payload, drifted transactions, explanations queue and result tables in an Apache Hive data warehouse that use the data description language statements (DDLs) that are generated as part of running the previous common configuration notebook.

# ## Contents
#
# * [1. Setup](#setup)
# * [2. Configure Watson OpenScale](#openscale)
# * [3. Set up Subscription](#subscription)
# * [4. Quality monitoring](#quality)
# * [5. Drift monitoring](#drift)
# * [6. Fairness monitoring](#fairness)
# * [7. Explainability monitoring](#explainability)

# # 1. Setup <a name="setup"></a>

# ## Package installation
#
# First import some of the packages you need to use. After you finish installing the following software packages, restart the kernel.

import warnings
warnings.filterwarnings('ignore')
# %env PIP_DISABLE_PIP_VERSION_CHECK=1

# !pip install ibm-watson-openscale --no-cache | tail -n 1

# !pip show ibm-watson-openscale

# ## Configure credentials
#
# Provide your IBM Watson OpenScale credentials in the following cell:

WOS_CREDENTIALS = {
    "url": "<cluster-url>",
    "username": "<username>",
    "password": "<password>",
    "instance_id": "<openscale instance id>"
}

# ## Specify model details

# ### Service provider and subscription metadata

# +
# Service Provider

SERVICE_PROVIDER_NAME = "<service-provider-name>"
SERVICE_PROVIDER_DESCRIPTION = "<service-provider-description>"

# Subscription

SUBSCRIPTION_NAME = "<subscription-name>"
SUBSCRIPTION_DESCRIPTION = "<subscription-description>"
# -

# ### IBM Analytics Engine - Spark
#
# Make sure that the Apache Spark manager on IBM Analytics Engine is running, and then provide the following details:
#
# - IAE_SPARK_DISPLAY_NAME: _Display Name of the Spark instance in IBM Analytics Engine_
# - IAE_SPARK_JOBS_ENDPOINT: _Spark Jobs Endpoint for IBM Analytics Engine_
# - IBM_CPD_VOLUME: _IBM Cloud Pak for Data storage volume name_
# - IBM_CPD_USERNAME: _IBM Cloud Pak for Data username_
# - IBM_CPD_APIKEY: _IBM Cloud Pak for Data API key_
# - IAE_SPARK_DESCRIPTION: _Custom description for the Spark instance_

IAE_SPARK_DISPLAY_NAME = "<spark-engine-name>"
IAE_SPARK_JOBS_ENDPOINT = "<spark-job-endpoint-for-ibm-analytics-engine>"
IBM_CPD_VOLUME = "<ibm-cpd-volume>"
IBM_CPD_USERNAME = "<ibm-cloud-pak-for-data-username>"
IBM_CPD_APIKEY = "<ibm-cloud-pak-for-data-apikey>"
IAE_SPARK_NAME = "<iae-spark-name>"
IAE_SPARK_DESCRIPTION = "<iae-spark-description>"

# #### Provide Spark Resource Settings
#
# To configure how much of your Spark Cluster resources this job can consume, edit the following values:
#
# - max_num_executors: _Maximum Number of executors to launch for this session_
# - min_executors: _Minimum Number of executors to launch for this session_
# - executor_cores: _Number of cores to use for each executor_   
# - executor_memory: _Amount of memory (in GBs) to use per executor process_
# - driver_cores: _Number of cores to use for the driver process_
# - driver_memory: _Amount of memory (in GBs) to use for the driver process_

spark_parameters = {
    "max_num_executors": 2,
    "min_num_executors": 1,
    "executor_cores": 3,
    "executor_memory": 2,
    "driver_cores": 2,
    "driver_memory": 2
}

# ### Apache Hive (Non-Kerberized)
#
# The Apache Spark manager on IBM Analytics Engine only supports an Apache Hive data warehouse that is not Kerberos-enabled. To connect to Apache Hive, you must provide the following details:
#
# - HIVE_CONNECTION_NAME: _Custom display name for the Hive Connection_
# - HIVE_CONNECTION_DESCRIPTION: _Custom description for the Hive connection_
# - HIVE_METASTORE_URI: _Thrift URI for Hive Metastore to connect to_

HIVE_CONNECTION_NAME = "<hive-connection-name>"
HIVE_CONNECTION_DESCRIPTION = "<hive-connection-description>"
HIVE_METASTORE_URI = "<hive-metastore-uri>"

# ### Feedback table metadata
#
# The quality monitor stores metadata in the feedback table. To configure the quality monitor, you must provide the following details. To skip quality monitoring, run the following cell to initialize variables with the value of `None`.
#
# - FEEDBACK_DATABASE_NAME: _Database name where feedback table is present_
# - FEEDBACK_SCHEMA_NAME: _Schema name where feedback table is present_
# - FEEDBACK_TABLE_NAME: _Name of the feedback table_

# +
#feedback

FEEDBACK_DATABASE_NAME = None
FEEDBACK_TABLE_NAME = None
# -

# ### Payload and drift table metadata
#
# The drift monitor stores metadata in the payload and drift tables. To configure the drift monitor, you must provide the following details. To skip drift monitoring, run the following cell to initialize variables with the value of `None`.
#
# - PAYLOAD_DATABASE_NAME: _Database name where payload logging table is present_
# - PAYLOAD_SCHEMA_NAME: _Schema name where payload logging table is present_
# - PAYLOAD_TABLE_NAME: _Name of the payload logging table_
# - DRIFT_DATABASE_NAME: _Database name where drifted transactions table is present_
# - DRIFT_SCHEMA_NAME: _Schema name where drifted transactions table is present_
# - DRIFT_TABLE_NAME: _Name of the drifted transactions table_

# +
#payload logging

PAYLOAD_DATABASE_NAME = None
PAYLOAD_TABLE_NAME = None

#drift

DRIFT_DATABASE_NAME = None
DRIFT_TABLE_NAME = None
# -

# ### Explainability table metadata
#
# The explainability monitor requires the queue and result tables. The payload table can also be used as the queue table. To configure the explainability monitor, you must provide the following details. To skip explainability monitoring, run the following cell to initialize variables with the value of `None`.
#
# - EXPLAINABILITY_DATABASE_NAME: _Database name where explanations queue, result tables are present_
# - EXPLAINABILITY_QUEUE_TABLE_NAME: _Name of the explanations queue table_
# - EXPLAINABILITY_RESULT_TABLE_NAME: _Name of the explanations result table_

# +
#explainability

EXPLAINABILITY_DATABASE_NAME = None
EXPLAINABILITY_QUEUE_TABLE_NAME = None
EXPLAINABILITY_RESULT_TABLE_NAME = None
# -

# # 2. Configure Watson OpenScale <a name="openscale"></a>

# ### Import the required libraries and set up the Watson OpenScale client

# +
from ibm_cloud_sdk_core.authenticators import CloudPakForDataAuthenticator
from ibm_watson_openscale import *
from ibm_watson_openscale.supporting_classes.enums import *
from ibm_watson_openscale.supporting_classes import *
from ibm_watson_openscale.base_classes.watson_open_scale_v2 import *

authenticator = CloudPakForDataAuthenticator(
        url=WOS_CREDENTIALS["url"],
        username=WOS_CREDENTIALS["username"],
        password=WOS_CREDENTIALS["password"],
        disable_ssl_verification=True
    )

wos_client = APIClient(authenticator=authenticator, service_url=WOS_CREDENTIALS["url"], service_instance_id=WOS_CREDENTIALS["instance_id"])
data_mart_id=WOS_CREDENTIALS["instance_id"]
# -

# ### Display Watson OpenScale datamart details

wos_client.data_marts.show()

# ### Create a service provider

# +
# Delete existing service provider with the same name as provided

service_providers = wos_client.service_providers.list().result.service_providers
for provider in service_providers:
    if provider.entity.name == SERVICE_PROVIDER_NAME:
        wos_client.service_providers.delete(service_provider_id=provider.metadata.id)
        break

# +
# Add Service Provider

added_service_provider_result = wos_client.service_providers.add(
        name=SERVICE_PROVIDER_NAME,
        description=SERVICE_PROVIDER_DESCRIPTION,
        service_type=ServiceTypes.CUSTOM_MACHINE_LEARNING,
        credentials={},
        operational_space_id="production",
        background_mode=False
    ).result

service_provider_id = added_service_provider_result.metadata.id

wos_client.service_providers.show()
# -

service_provide_details = wos_client.service_providers.get(service_provider_id=service_provider_id).result
print(service_provide_details)

# ### Create integrated systems for Spark Engine and Hive

# +
# Delete existing spark and hive integrated systems if present

integrated_systems = IntegratedSystems(wos_client).list().result.integrated_systems

for system in integrated_systems:
    if system.entity.name in (IAE_SPARK_NAME, HIVE_CONNECTION_NAME):
        print("Deleting integrated system {}".format(system.entity.name))
        IntegratedSystems(wos_client).delete(integrated_system_id=system.metadata.id)
# -

# #### Spark Engine

# +
spark_engine_details = IntegratedSystems(wos_client).add(
    name=IAE_SPARK_NAME,
    description=IAE_SPARK_DESCRIPTION,
    type="spark",
    credentials={
        "username": IBM_CPD_USERNAME,
        "apikey": IBM_CPD_APIKEY
    },
    connection={
        "display_name": IAE_SPARK_DISPLAY_NAME,
        "endpoint": IAE_SPARK_JOBS_ENDPOINT,
        "volume": IBM_CPD_VOLUME,
        "location_type": "cpd_iae"
    }
).result

spark_engine_id = spark_engine_details.metadata.id
print(spark_engine_details)
# -

# #### Hive

# +
hive_connection = {}
if HIVE_METASTORE_URI is not None:
    hive_connection["metastore_url"] = HIVE_METASTORE_URI
    hive_connection["location_type"] = "metastore"

hive_connection_details = IntegratedSystems(wos_client).add(
    name=HIVE_CONNECTION_NAME,
    description=HIVE_CONNECTION_DESCRIPTION,
    type="hive",
    credentials={
        
    },
    connection=hive_connection
).result

hive_connection_id=hive_connection_details.metadata.id
print(hive_connection_details)
# -

# # 3. Set up a subscription<a name="subscription"></a>

# +
# Delete an existing subscription with the provided name

subscriptions = wos_client.subscriptions.list().result.subscriptions
for sub in subscriptions:
    if sub.entity.deployment.name == SUBSCRIPTION_NAME:
        wos_client.subscriptions.delete(subscription_id=sub.metadata.id)
        break

# Display all subscriptions
wos_client.subscriptions.show()
# -

# ### Set subscription metadata
#
# In the following cell, type a path to the common configuration JSON file that you created by running the [common configuration notebook](https://github.com/IBM/watson-openscale-samples/blob/main/Cloud%20Pak%20for%20Data/Batch%20Support/Configuration%20generation%20for%20OpenScale%20batch%20subscription.ipynb). After you edit the path information, run the cell to set the asset details and properties, the deployment details, the analytics engine details, and to add the required tables as data sources.

# +
import uuid

common_configuration = None
with open("/path/to/dir/containing/common_config.json", "r") as fp:
    configuration_json = json.load(fp)
    common_configuration = configuration_json.get("common_configuration")
    if common_configuration is None:
        print("Please provide the correct path to the common configuration JSON")
    
# Set asset details
asset = Asset(
    asset_id=str(uuid.uuid4()),
    url="",
    name=SUBSCRIPTION_NAME,
    asset_type=AssetTypes.MODEL,
    input_data_type=InputDataType.STRUCTURED,
    problem_type=ProblemType.BINARY_CLASSIFICATION
)

# Set deployment details
asset_deployment = AssetDeploymentRequest(
    deployment_id=str(uuid.uuid4()),
    name=SUBSCRIPTION_NAME,
    description=SUBSCRIPTION_DESCRIPTION,
    deployment_type="batch"
)

# Set asset properties 
asset_properties_request = AssetPropertiesRequest(
    label_column=common_configuration["label_column"],
    probability_fields=[common_configuration["probability"]],
    prediction_field=common_configuration["prediction"],
    feature_fields=common_configuration["feature_columns"],
    categorical_fields=common_configuration["categorical_columns"]
)

# Set analytics engine details
analytics_engine = AnalyticsEngine(
    type="spark",
    integrated_system_id=spark_engine_id,
    parameters = spark_parameters
)

# Add selected tables as data sources
data_sources = []
if FEEDBACK_DATABASE_NAME is not None and FEEDBACK_TABLE_NAME is not None:
    feedback_data_source = DataSource(
        type="feedback", 
        database_name=FEEDBACK_DATABASE_NAME,
        schema_name=FEEDBACK_DATABASE_NAME,
        table_name=FEEDBACK_TABLE_NAME, 
        connection=DataSourceConnection(
            type="hive", 
            integrated_system_id=hive_connection_id
        )
    )
    data_sources.append(feedback_data_source)
    
if PAYLOAD_DATABASE_NAME is not None and PAYLOAD_TABLE_NAME is not None \
    and DRIFT_DATABASE_NAME is not None and DRIFT_TABLE_NAME is not None:
    payload_logging_data_source = DataSource(
        type="payload", 
        database_name=PAYLOAD_DATABASE_NAME,
        schema_name=PAYLOAD_DATABASE_NAME,
        table_name=PAYLOAD_TABLE_NAME, 
        connection=DataSourceConnection(
            type="hive", 
            integrated_system_id=hive_connection_id
        )
    )
    
    drifted_transactions_table_data_source = DataSource(
        type="drift", 
        database_name=DRIFT_DATABASE_NAME,
        schema_name=DRIFT_DATABASE_NAME,
        table_name=DRIFT_TABLE_NAME, 
        connection=DataSourceConnection(
            type="hive", 
            integrated_system_id=hive_connection_id
        )
    )
    
    data_sources.append(payload_logging_data_source)
    data_sources.append(drifted_transactions_table_data_source)

if EXPLAINABILITY_DATABASE_NAME is not None and EXPLAINABILITY_QUEUE_TABLE_NAME is not None \
    and EXPLAINABILITY_RESULT_TABLE_NAME is not None:
    explainability_data_source = DataSource(
        type="explain", 
        database_name=EXPLAINABILITY_DATABASE_NAME,
        schema_name=EXPLAINABILITY_DATABASE_NAME,
        table_name=EXPLAINABILITY_QUEUE_TABLE_NAME, 
        connection=DataSourceConnection(
            type="hive", 
            integrated_system_id=hive_connection_id
        ),
        parameters={
            "result_table_name": EXPLAINABILITY_RESULT_TABLE_NAME
        }
    )
    
    data_sources.append(explainability_data_source)

# +
# Adding the subscription

subscription_details = Subscriptions(wos_client).add(
    data_mart_id=data_mart_id,
    service_provider_id=service_provider_id,
    asset=asset,
    deployment=asset_deployment,
    asset_properties=asset_properties_request,
    analytics_engine=analytics_engine,
    data_sources=data_sources).result

subscription_id = subscription_details.metadata.id
print(subscription_details)

# +
import time
# Checking subscription status

state = wos_client.subscriptions.get(subscription_id).result.entity.status.state

while state not in ["active", "error"]:
    state = wos_client.subscriptions.get(subscription_id).result.entity.status.state
    print(state)
    time.sleep(5)

# +
# Add training, output, and input data schemas to the subscription

training_data_schema_patch_document=[
    JsonPatchOperation(op=OperationTypes.REPLACE, path='/asset_properties/training_data_schema', value=common_configuration["training_data_schema"])
]

input_data_schema_patch_document=[
    JsonPatchOperation(op=OperationTypes.REPLACE, path='/asset_properties/input_data_schema', value=common_configuration["input_data_schema"])
]

output_data_schema_patch_document=[
    JsonPatchOperation(op=OperationTypes.REPLACE, path='/asset_properties/output_data_schema', value=common_configuration["output_data_schema"])
]

wos_client.subscriptions.update(subscription_id=subscription_id, patch_document=training_data_schema_patch_document)
wos_client.subscriptions.update(subscription_id=subscription_id, patch_document=input_data_schema_patch_document)
wos_client.subscriptions.update(subscription_id=subscription_id, patch_document=output_data_schema_patch_document)
# -

# # 4. Quality monitoring <a name="quality"></a>

# ### Enable the quality monitor
#
# In the following code cell, default values are set for the quality monitor. You can change the default values by updating the optional `min_feedback_data_size` attribute in the `parameters` dict and set the quality threshold in the `thresholds` list.

# +
import time

target = Target(
    target_type=TargetTypes.SUBSCRIPTION,
    target_id=subscription_id
)

parameters = {
    "min_feedback_data_size": 200
}

thresholds = [{
        "metric_id": "area_under_roc",
        "type": "lower_limit",
        "value": 0.8
}]

quality_monitor_details = wos_client.monitor_instances.create(
    data_mart_id=data_mart_id,
    monitor_definition_id=wos_client.monitor_definitions.MONITORS.QUALITY.ID,
    target=target,
    parameters=parameters,
    thresholds=thresholds
).result

quality_monitor_instance_id = quality_monitor_details.metadata.id
print(quality_monitor_details)
# -

# ### Check monitor instance status

# +
quality_status = None

while quality_status not in ("active", "error"):
    monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=quality_monitor_instance_id).result
    quality_status = monitor_instance_details.entity.status.state
    if quality_status not in ("active", "error"):
        print(datetime.utcnow().strftime('%H:%M:%S'), quality_status)
        time.sleep(30)
        
print(datetime.utcnow().strftime('%H:%M:%S'), quality_status)
# -

monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=quality_monitor_instance_id).result
print(monitor_instance_details)

# ### Run an on-demand evaluation

# +
# Trigger on-demand run

monitoring_run_details = wos_client.monitor_instances.run(monitor_instance_id=quality_monitor_instance_id).result
monitoring_run_id=monitoring_run_details.metadata.id

print(monitoring_run_details)

# +
# Check run status

quality_run_status = None
while quality_run_status not in ("finished", "error"):
    monitoring_run_details = wos_client.monitor_instances.get_run_details(monitor_instance_id=quality_monitor_instance_id, monitoring_run_id=monitoring_run_id).result
    quality_run_status = monitoring_run_details.entity.status.state
    if quality_run_status not in ("finished", "error"):
        print(datetime.utcnow().strftime("%H:%M:%S"), quality_run_status)
        time.sleep(30)
        
print(datetime.utcnow().strftime("%H:%M:%S"), quality_run_status)
# -

# ### Display quality metrics

wos_client.monitor_instances.show_metrics(monitor_instance_id=quality_monitor_instance_id)

# # 5. Drift monitoring <a name="drift"></a>

# ### Enable the drift monitor
#
# In the following code cell, type a path to the drift configuration tar ball.

wos_client.monitor_instances.upload_drift_model(
    model_path="/path/to/dir/containing/drift.tar.gz",
    data_mart_id=data_mart_id,
    subscription_id=subscription_id
).result

# In the following code cell, default values are set for the drift monitor. You can change the default values by updating the values in the `parameters` section. The `min_samples` parameter controls the number of records that triggers the drift monitor to run. The `drift_threshold` parameter sets the threshold in decimal format for the drift percentage to trigger an alert. The `train_drift_model` parameter controls whether to re-train the model based on the drift analysis.

# +
import time

target = Target(
    target_type=TargetTypes.SUBSCRIPTION,
    target_id=subscription_id
)

parameters = {
    "min_samples": 100,
    "drift_threshold": 0.05,
    "train_drift_model": False
}

drift_monitor_details = wos_client.monitor_instances.create(
    data_mart_id=data_mart_id,
    monitor_definition_id=wos_client.monitor_definitions.MONITORS.DRIFT.ID,
    target=target,
    parameters=parameters
).result

drift_monitor_instance_id = drift_monitor_details.metadata.id
print(drift_monitor_details)
# -

# ### Check monitor instance status

# +
drift_status = None

while drift_status not in ("active", "error"):
    monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=drift_monitor_instance_id).result
    drift_status = monitor_instance_details.entity.status.state
    if drift_status not in ("active", "error"):
        print(datetime.utcnow().strftime('%H:%M:%S'), drift_status)
        time.sleep(30)

print(datetime.utcnow().strftime('%H:%M:%S'), drift_status)
# -

# ### Run an on-demand evaluation

# +
# Check Drift monitor instance details

monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=drift_monitor_instance_id).result
print(monitor_instance_details)

# +
# Trigger on-demand run

monitoring_run_details = wos_client.monitor_instances.run(monitor_instance_id=drift_monitor_instance_id).result
monitoring_run_id=monitoring_run_details.metadata.id

print(monitoring_run_details)

# +
# Check run status

drift_run_status = None
while drift_run_status not in ("finished", "error"):
    monitoring_run_details = wos_client.monitor_instances.get_run_details(monitor_instance_id=drift_monitor_instance_id, monitoring_run_id=monitoring_run_id).result
    drift_run_status = monitoring_run_details.entity.status.state
    if drift_run_status not in ("finished", "error"):
        print(datetime.utcnow().strftime("%H:%M:%S"), drift_run_status)
        time.sleep(30)
        
print(datetime.utcnow().strftime("%H:%M:%S"), drift_run_status)
# -

# ### Display drift metrics

wos_client.monitor_instances.show_metrics(monitor_instance_id=drift_monitor_instance_id)

# # 6. Fairness monitoring <a name="fairness"></a>

# ### Enable the fairness monitor
#
# The following code cell, will enable the fairness monitor.

# +
target = Target(
    target_type=TargetTypes.SUBSCRIPTION,
    target_id=subscription_id
)

parameters = configuration_json["fairness_configuration"]["parameters"]
thresholds = configuration_json["fairness_configuration"]["thresholds"]

fairness_monitor_details = wos_client.monitor_instances.create(
    data_mart_id=data_mart_id,
    monitor_definition_id=wos_client.monitor_definitions.MONITORS.FAIRNESS.ID,
    target=target,
    parameters=parameters,
    thresholds=thresholds
).result

fairness_monitor_instance_id = fairness_monitor_details.metadata.id
print(fairness_monitor_details)
# -

# ### Check monitor instance status

# +
fairness_state = fairness_monitor_details.entity.status.state

while fairness_state not in ("active", "error"):
    print(datetime.utcnow().strftime('%H:%M:%S'), fairness_state)
    monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=fairness_monitor_instance_id).result
    fairness_state = monitor_instance_details.entity.status.state
    time.sleep(30)

print(datetime.utcnow().strftime('%H:%M:%S'), fairness_state)
# -

# ### Run an on-demand evaluation

# +
# Trigger on-demand run

monitoring_run_details = wos_client.monitor_instances.run(monitor_instance_id=fairness_monitor_instance_id).result
monitoring_run_id=monitoring_run_details.metadata.id

print(monitoring_run_details)

# +
# Check run status

fairness_run_status = monitoring_run_details.entity.status.state
while fairness_run_status not in ("finished", "error"):
    print(datetime.utcnow().strftime("%H:%M:%S"), fairness_run_status)
    monitoring_run_details = wos_client.monitor_instances.get_run_details(monitor_instance_id=fairness_monitor_instance_id, monitoring_run_id=monitoring_run_id).result
    fairness_run_status = monitoring_run_details.entity.status.state
    time.sleep(30)
        
print(datetime.utcnow().strftime("%H:%M:%S"), fairness_run_status)
# -

# ### Display fairness metrics

wos_client.monitor_instances.show_metrics(monitor_instance_id=fairness_monitor_instance_id)

# # 7. Explainability monitoring <a name="explainability"></a>

# ### Enable the explainability monitor

# +
import time

target = Target(
    target_type=TargetTypes.SUBSCRIPTION,
    target_id=subscription_id
)

explainability_configuration = configuration_json.get("explainability_configuration")
if explainability_configuration is None:
    raise Exception("Please provide the explainability configuration details.")
        
parameters = {
    "training_statistics": explainability_configuration
}

explainability_monitor_details = wos_client.monitor_instances.create(
    data_mart_id=data_mart_id,
    monitor_definition_id=wos_client.monitor_definitions.MONITORS.EXPLAINABILITY.ID,
    target=target,
    parameters=parameters
).result

explainability_monitor_instance_id = explainability_monitor_details.metadata.id
print(explainability_monitor_details)

# + [markdown] tags=[]
# ### Check monitor instance status

# +
explainability_status = None

while explainability_status not in ("active", "error"):
    monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=explainability_monitor_instance_id).result
    explainability_status = monitor_instance_details.entity.status.state
    if explainability_status not in ("active", "error"):
        print(datetime.utcnow().strftime('%H:%M:%S'), explainability_status)
        time.sleep(30)

print(datetime.utcnow().strftime('%H:%M:%S'), explainability_status)
# -

# ### Upload perturbations scoring response archive
# In the following code cell, type the path to the explainability perturbations archive tar ball.

# +
with open("/path/to/dir/containing/perturbations.tar.gz", mode="rb") as perturbations_tar:
    wos_client.monitor_instances.upload_explainability_archive(subscription_id=subscription_id, archive=perturbations_tar)

print("Uploaded perturbations scoring response archive successfully.")
# -

# ### Run an on-demand evaluation

# +
# Check Explainbility monitor instance details

monitor_instance_details = wos_client.monitor_instances.get(monitor_instance_id=explainability_monitor_instance_id).result
print(monitor_instance_details)

# +
# Trigger on-demand run

monitoring_run_details = wos_client.monitor_instances.run(monitor_instance_id=explainability_monitor_instance_id).result
monitoring_run_id=monitoring_run_details.metadata.id

print(monitoring_run_details)

# +
# Check run status

explainability_run_status = None
while explainability_run_status not in ("finished", "error"):
    monitoring_run_details = wos_client.monitor_instances.get_run_details(monitor_instance_id=explainability_monitor_instance_id, monitoring_run_id=monitoring_run_id).result
    explainability_run_status = monitoring_run_details.entity.status.state
    if explainability_run_status not in ("finished", "error"):
        print(datetime.utcnow().strftime("%H:%M:%S"), explainability_run_status)
        time.sleep(60)
        
print(datetime.utcnow().strftime("%H:%M:%S"), explainability_run_status)
# -

# ### Display sample explanations

explanations = wos_client.monitor_instances.get_all_explaination_tasks(subscription_id=subscription_id).result
print(explanations)

# ## Congratulations!
#
# You have finished the Batch demo for IBM Watson OpenScale by using Apache Spark on Cloud Pak for Data IBM Analytics Engine. You can now view the [Watson OpenScale Dashboard](https://url-to-your-cp4d-cluster/aiopenscale). Click the tile for the **German Credit model** to see the quality, drift and fairness monitors. Click the timeseries graph to get detailed information on transactions during a specific time window.

StarcoderdataJupyterScriptsDedupFiltered