code: def test_confidence_thresholding_2thresholds_3d_vis_api(csv_filename):
      """Ensure pdf and png figures can be saved via visualization API call.
  
      :param csv_filename: csv fixture from tests.fixtures.filenames.csv_filename
      :return: None
      """
      input_features = [
          text_feature(
              encoder={
                  "vocab_size": 10,
                  "min_len": 1,
                  "type": "stacked_cnn",
              }
          ),
          number_feature(),
          category_feature(
              encoder={"vocab_size": 10, "embedding_size": 5}
          ),
          set_feature(),
          sequence_feature(
              encoder={"vocab_size": 10, "max_len": 10, "type": "embed"}
          ),
      ]
      output_features = [
          category_feature(
              decoder={"vocab_size": 2}, reduce_input="sum"
          ),
          category_feature(
              decoder={"vocab_size": 2}, reduce_input="sum"
          ),
      ]
      encoder = "parallel_cnn"
      with TemporaryDirectory() as tmpvizdir:
          # Generate test data
          data_csv = generate_data(
              input_features,
              output_features,
              os.path.join(tmpvizdir, csv_filename),
          )
          input_features[0][ENCODER][TYPE] = encoder
          model = run_api_experiment(input_features, output_features)
          test_df, train_df, val_df = obtain_df_splits(data_csv)
          _, _, output_dir = model.train(
              training_set=train_df,
              validation_set=val_df,
              output_directory=os.path.join(tmpvizdir, "results"),
          )
          test_stats, predictions, _ = model.evaluate(
              dataset=test_df,
              collect_predictions=True,
              output_directory=output_dir,
          )
  
          output_feature_name1 = output_features[0]["name"]
          output_feature_name2 = output_features[1]["name"]
  
          ground_truth_metadata = model.training_set_metadata
          feature1_cols = [
              f"{output_feature_name1}_probabilities_{label}"
              for label in ground_truth_metadata[output_feature_name1][
                  "idx2str"
              ]
          ]
          feature2_cols = [
              f"{output_feature_name2}_probabilities_{label}"
              for label in ground_truth_metadata[output_feature_name2][
                  "idx2str"
              ]
          ]
  
          # probabilities need to be list of lists containing each row data from the
          # probability columns ref: https://ludwig-ai.github.io/ludwig-docs/latest/user_guide/api/LudwigModel#evaluate
          probability1 = predictions.loc[:, feature1_cols].values
          probability2 = predictions.loc[:, feature2_cols].values
  
          target_predictions1 = test_df[output_feature_name1]
          target_predictions2 = test_df[output_feature_name2]
          ground_truth1 = np.asarray(
              [
                  ground_truth_metadata[output_feature_name1][
                      "str2idx"
                  ][prediction]
                  for prediction in target_predictions1
              ]
          )
          ground_truth2 = np.asarray(
              [
                  ground_truth_metadata[output_feature_name2][
                      "str2idx"
                  ][prediction]
                  for prediction in target_predictions2
              ]
          )
          viz_outputs = ("pdf", "png")
          for viz_output in viz_outputs:
              vis_output_pattern_pdf = os.path.join(
                  output_dir, f"*.{viz_output}"
              )
              visualize.confidence_thresholding_2thresholds_3d(
                  [probability1, probability2],
                  [ground_truth1, ground_truth2],
                  model.training_set_metadata,
                  [output_feature_name1, output_feature_name2],
                  labels_limit=0,
                  output_directory=output_dir,
                  file_format=viz_output,
              )
              figure_cnt = glob.glob(vis_output_pattern_pdf)
              assert 1 == len(figure_cnt)
  
imports: import glob
  import logging
  import os
  from tempfile import TemporaryDirectory
  import numpy
  import pytest
  from ludwig import visualize
  from ludwig.api import LudwigModel, TrainingStats
  from ludwig.constants import BATCH_SIZE, ENCODER, NAME, PREDICTIONS, PROBABILITIES, PROBABILITY, TRAINER, TYPE
  from ludwig.data.split import get_splitter
  from ludwig.globals import HYPEROPT_STATISTICS_FILE_NAME
  from ludwig.utils.data_utils import read_csv
  from tests.integration_tests.utils import bag_feature, binary_feature, category_feature, generate_data, LocalTestBackend, number_feature, sequence_feature, set_feature, text_feature
label_desc: Use image node_id 18 for calling a global function with example usage: test_confidence_thresholding_2thresholds_3d_vis_api(csv_filename) without return types