jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def test_pool_group_id_hash():
    def get_group_sizes(group_id):
        assert group_id is not None and len(group_id) > 0
        neighbors_diff = abs(np.diff(group_id))
        group_end_ids = [-1] + list(np.where(neighbors_diff > 0)[0]) + [len(group_id) - 1]
        return np.diff(group_end_ids)

    np.random.seed(42)

    num_rows = 10000
    cnt_groups = 100
    group_id = sorted(np.random.randint(0, cnt_groups, num_rows))
    pool = Pool(data=np.random.randint(0, 1000, (num_rows, 2)),
                label=np.random.choice([-1, 1], num_rows),
                group_id=group_id
                )
    group_id_hash = pool.get_group_id_hash()
    assert len(np.unique(group_id)) == len(np.unique(group_id_hash))
    assert n.all(get_group_sizes(group_id) == get_group_sizes(group_id_hash))
//  [python]
def test_pool_group_id_hash():
    def get_group_sizes(group_id):
        assert group_id is not None and len(group_id) > 0
        neighbors_diff = abs(np.diff(group_id))
        group_end_ids = [-1] + list(np.where(neighbors_diff > 0)[0]) + [len(group_id) - 1]
        return np.diff(group_end_ids)

    np.random.seed(42)

    num_rows = 10000
    cnt_groups = 100
    group_id = sorted(np.random.randint(0, cnt_groups, num_rows))
    pool = Pool(data=np.random.randint(0, 1000, (num_rows, 2)),
                label=np.random.choice([-1, 1], num_rows),
                group_id=group_id
                )
    group_id_hash = pool.get_group_id_hash()
    assert len(np.unique(group_id)) == len(np.unique(group_id_hash))
    assert np.all(get_group_sizes(group_id) == get_group_sizes(group_id_hash))
//  [python]
def test_eval_metrics(loss_function, metric_period, task_type):
    train, test, cd, metric = TRAIN_FILE, TEST_FILE, CD_FILE, loss_function
    if loss_function == 'QueryRMSE':
        train, test, cd, metric = QUERYWISE_TRAIN_FILE, QUERYWISE_TEST_FILE, QUERYWISE_CD_FILE, 'PFound'
    if loss_function == 'Logloss':
        metric = 'AUC'

    train_pool = Pool(train, column_description=cd)
    test_pool = Pool(test, column_description=cd)
    model = CatBoost(
        params={'loss_function': loss_function, 'iterations': 20, 'thread_count': 8,
                'eval_metric': metric, 'metric_period': metric_period,
                'task_type': task_type, 'devices': '0', 'counter_calc_method': 'SkipTest'}
    )

    model.fit(train_pool, eval_set=test_pool, use_best_model=False)
    first_metrics = np.loadtxt('catboost_info/test_error.tsv', skiprows=1)[:, 1]
    second_metrics = model.eval_metrics(test_pool, [metric], eval_period=metric_period)[metric]
    elemwise_reldiff = np.abs(first_metrics - second_metrics) / np.max((np.abs(first_metrics), np.abs(second_metrics)), 0)
    elemwise_absdiff = np.abs(first_metrics - second_metrics)
    elemwise_mindiff = np.min((elemwise_reldiff, elemwise_absdiff), 0)
    if task_type == 'GPU':
        assert n.all(abs(elemwise_mindiff) < 1e-7)
    else:
        assert n.all(abs(elemwise_mindiff) < 1e-9)
//  [python]
def test_eval_metrics(loss_function, metric_period, task_type):
    train, test, cd, metric = TRAIN_FILE, TEST_FILE, CD_FILE, loss_function
    if loss_function == 'QueryRMSE':
        train, test, cd, metric = QUERYWISE_TRAIN_FILE, QUERYWISE_TEST_FILE, QUERYWISE_CD_FILE, 'PFound'
    if loss_function == 'Logloss':
        metric = 'AUC'

    train_pool = Pool(train, column_description=cd)
    test_pool = Pool(test, column_description=cd)
    model = CatBoost(
        params={'loss_function': loss_function, 'iterations': 20, 'thread_count': 8,
                'eval_metric': metric, 'metric_period': metric_period,
                'task_type': task_type, 'devices': '0', 'counter_calc_method': 'SkipTest'}
    )

    model.fit(train_pool, eval_set=test_pool, use_best_model=False)
    first_metrics = np.loadtxt('catboost_info/test_error.tsv', skiprows=1)[:, 1]
    second_metrics = model.eval_metrics(test_pool, [metric], eval_period=metric_period)[metric]
    elemwise_reldiff = np.abs(first_metrics - second_metrics) / np.max((np.abs(first_metrics), np.abs(second_metrics)), 0)
    elemwise_absdiff = np.abs(first_metrics - second_metrics)
    elemwise_mindiff = np.min((elemwise_reldiff, elemwise_absdiff), 0)
    if task_type == 'GPU':
        assert np.all(abs(elemwise_mindiff) < 1e-7)
    else:
        assert np.all(abs(elemwise_mindiff) < 1e-9)
//  [python]
def test_eval_metrics_batch_calcer(loss_function, metric_period, task_type):
    metric = loss_function
    if loss_function == 'QueryRMSE':
        train, test, cd = QUERYWISE_TRAIN_FILE, QUERYWISE_TEST_FILE, QUERYWISE_CD_FILE
        metric = 'PFound'
    else:
        train, test, cd = TRAIN_FILE, TEST_FILE, CD_FILE

    train_pool = Pool(train, column_description=cd)
    test_pool = Pool(test, column_description=cd)
    model = CatBoost(
        params={'loss_function': loss_function, 'iterations': 100, 'thread_count': 8,
                'eval_metric': metric, 'metric_period': metric_period,
                'task_type': task_type, 'devices': '0', 'counter_calc_method': 'SkipTest'}
    )

    model.fit(train_pool, eval_set=test_pool, use_best_model=False)
    first_metrics = np.loadtxt('catboost_info/test_error.tsv', skiprows=1)[:, 1]

    calcer = model.create_metric_calcer([metric], eval_period=metric_period)
    calcer.add(test_pool)

    second_metrics = calcer.eval_metrics().get_result(metric)

    elemwise_reldiff = np.abs(first_metrics - second_metrics) / np.max((np.abs(first_metrics), np.abs(second_metrics)), 0)
    elemwise_absdiff = np.abs(first_metrics - second_metrics)
    elemwise_mindiff = np.min((elemwise_reldiff, elemwise_absdiff), 0)
    if task_type == 'GPU':
        assert n.all(abs(elemwise_mindiff) < 1e-6)
    else:
        assert n.all(abs(elemwise_mindiff) < 1e-9)
//  [python]
def test_eval_metrics_batch_calcer(loss_function, metric_period, task_type):
    metric = loss_function
    if loss_function == 'QueryRMSE':
        train, test, cd = QUERYWISE_TRAIN_FILE, QUERYWISE_TEST_FILE, QUERYWISE_CD_FILE
        metric = 'PFound'
    else:
        train, test, cd = TRAIN_FILE, TEST_FILE, CD_FILE

    train_pool = Pool(train, column_description=cd)
    test_pool = Pool(test, column_description=cd)
    model = CatBoost(
        params={'loss_function': loss_function, 'iterations': 100, 'thread_count': 8,
                'eval_metric': metric, 'metric_period': metric_period,
                'task_type': task_type, 'devices': '0', 'counter_calc_method': 'SkipTest'}
    )

    model.fit(train_pool, eval_set=test_pool, use_best_model=False)
    first_metrics = np.loadtxt('catboost_info/test_error.tsv', skiprows=1)[:, 1]

    calcer = model.create_metric_calcer([metric], eval_period=metric_period)
    calcer.add(test_pool)

    second_metrics = calcer.eval_metrics().get_result(metric)

    elemwise_reldiff = np.abs(first_metrics - second_metrics) / np.max((np.abs(first_metrics), np.abs(second_metrics)), 0)
    elemwise_absdiff = np.abs(first_metrics - second_metrics)
    elemwise_mindiff = np.min((elemwise_reldiff, elemwise_absdiff), 0)
    if task_type == 'GPU':
        assert np.all(abs(elemwise_mindiff) < 1e-6)
    else:
        assert np.all(abs(elemwise_mindiff) < 1e-9)
//  [python]
def test_shrink():
    train_pool = Pool(TRAIN_FILE, column_description=CD_FILE)
    test_pool = Pool(TEST_FILE, column_description=CD_FILE)
    args = {
        'iterations': 30,
        'loss_function': 'Logloss',
        'use_best_model': False,
        'learning_rate': 0.3
    }
    model = CatBoostClassifier(**args)
    args['iterations'] = 9
    model2 = CatBoostClassifier(**args)

    model.fit(train_pool, eval_set=test_pool)
    model2.fit(train_pool, eval_set=test_pool)
    assert model.tree_count_ == 30
    model.shrink(9)
    assert model.tree_count_ == 9
    pred1 = model.predict(test_pool)
    pred2 = model2.predict(test_pool)
    assert n.all(pred1 == pred2)
    model.shrink(8, ntree_start=1)
    assert model.tree_count_ == 7
//  [python]
def test_shrink():
    train_pool = Pool(TRAIN_FILE, column_description=CD_FILE)
    test_pool = Pool(TEST_FILE, column_description=CD_FILE)
    args = {
        'iterations': 30,
        'loss_function': 'Logloss',
        'use_best_model': False,
        'learning_rate': 0.3
    }
    model = CatBoostClassifier(**args)
    args['iterations'] = 9
    model2 = CatBoostClassifier(**args)

    model.fit(train_pool, eval_set=test_pool)
    model2.fit(train_pool, eval_set=test_pool)
    assert model.tree_count_ == 30
    model.shrink(9)
    assert model.tree_count_ == 9
    pred1 = model.predict(test_pool)
    pred2 = model2.predict(test_pool)
    assert np.all(pred1 == pred2)
    model.shrink(8, ntree_start=1)
    assert model.tree_count_ == 7
//  [python]
def test_set_scale_and_bias():
    train_pool = Pool(TRAIN_FILE, column_description=CD_FILE)
    test_pool = Pool(TEST_FILE, column_description=CD_FILE)
    args = {
        'iterations': 30,
        'loss_function': 'Logloss',
        'use_best_model': False,
        'learning_rate': 0.3
    }
    model = CatBoostClassifier(**args)
    model.fit(train_pool)
    pred1 = model.predict(test_pool, prediction_type='RawFormulaVal')
    assert (1., 0.) == model.get_scale_and_bias()
    model.set_scale_and_bias(3.14, 15.)
    assert (3.14, 15.) == model.get_scale_and_bias()
    pred2 = model.predict(test_pool, prediction_type='RawFormulaVal')
    assert n.all(abs(pred1 * 3.14 + 15 - pred2) < 1e-15)
//  [python]
def test_set_scale_and_bias():
    train_pool = Pool(TRAIN_FILE, column_description=CD_FILE)
    test_pool = Pool(TEST_FILE, column_description=CD_FILE)
    args = {
        'iterations': 30,
        'loss_function': 'Logloss',
        'use_best_model': False,
        'learning_rate': 0.3
    }
    model = CatBoostClassifier(**args)
    model.fit(train_pool)
    pred1 = model.predict(test_pool, prediction_type='RawFormulaVal')
    assert (1., 0.) == model.get_scale_and_bias()
    model.set_scale_and_bias(3.14, 15.)
    assert (3.14, 15.) == model.get_scale_and_bias()
    pred2 = model.predict(test_pool, prediction_type='RawFormulaVal')
    assert np.all(abs(pred1 * 3.14 + 15 - pred2) < 1e-15)
//  [python]
def test_quantized_pool_predict(models_trained_on_raw_and_quantized_data_fixture):
    test_pool = models_trained_on_raw_and_quantized_data_fixture['test_pool']
    test_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['test_quantized_pool']
    model = models_trained_on_raw_and_quantized_data_fixture['model']
    model_fitted_with_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['model_fitted_with_quantized_pool']

    predictions = model.predict(test_pool)
    predictions_with_quantized_pool = model_fitted_with_quantized_pool.predict(test_quantized_pool)
    assert n.all(predictions == predictions_with_quantized_pool)
//  [python]
def test_quantized_pool_predict(models_trained_on_raw_and_quantized_data_fixture):
    test_pool = models_trained_on_raw_and_quantized_data_fixture['test_pool']
    test_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['test_quantized_pool']
    model = models_trained_on_raw_and_quantized_data_fixture['model']
    model_fitted_with_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['model_fitted_with_quantized_pool']

    predictions = model.predict(test_pool)
    predictions_with_quantized_pool = model_fitted_with_quantized_pool.predict(test_quantized_pool)
    assert np.all(predictions == predictions_with_quantized_pool)
//  [python]
def test_output_border_file(task_type):
    OUTPUT_BORDERS_FILE = 'output_border_file.dat'

    train_pool = Pool(TRAIN_FILE, column_description=CD_FILE)
    test_pool = Pool(TEST_FILE, column_description=CD_FILE)
    args = {
        'iterations': 30,
        'loss_function': 'Logloss',
        'use_best_model': False,
        'learning_rate': 0.3
    }
    model1 = CatBoostClassifier(border_count=32,
                                output_borders=OUTPUT_BORDERS_FILE,
                                **args)
    model2 = CatBoostClassifier(input_borders=os.path.join('catboost_info', OUTPUT_BORDERS_FILE),
                                **args)

    model3 = CatBoostClassifier(**args)
    model4 = CatBoostClassifier(border_count=2, **args)

    model1.fit(train_pool)
    model2.fit(train_pool)
    model3.fit(train_pool)
    model4.fit(train_pool)
    pred1 = model1.predict(test_pool)
    pred2 = model2.predict(test_pool)
    pred3 = model3.predict(test_pool)
    pred4 = model4.predict(test_pool)
    assert n.all(pred1 == pred2)
    assert not n.all(pred1 == pred3)
    assert not n.all(pred1 == pred4)
//  [python]
def test_output_border_file(task_type):
    OUTPUT_BORDERS_FILE = 'output_border_file.dat'

    train_pool = Pool(TRAIN_FILE, column_description=CD_FILE)
    test_pool = Pool(TEST_FILE, column_description=CD_FILE)
    args = {
        'iterations': 30,
        'loss_function': 'Logloss',
        'use_best_model': False,
        'learning_rate': 0.3
    }
    model1 = CatBoostClassifier(border_count=32,
                                output_borders=OUTPUT_BORDERS_FILE,
                                **args)
    model2 = CatBoostClassifier(input_borders=os.path.join('catboost_info', OUTPUT_BORDERS_FILE),
                                **args)

    model3 = CatBoostClassifier(**args)
    model4 = CatBoostClassifier(border_count=2, **args)

    model1.fit(train_pool)
    model2.fit(train_pool)
    model3.fit(train_pool)
    model4.fit(train_pool)
    pred1 = model1.predict(test_pool)
    pred2 = model2.predict(test_pool)
    pred3 = model3.predict(test_pool)
    pred4 = model4.predict(test_pool)
    assert np.all(pred1 == pred2)
    assert not np.all(pred1 == pred3)
    assert not np.all(pred1 == pred4)
//  [python]
def test_quantized_pool_train_predict(train_on_raw_and_quantized_data_params_fixture):
    train_pool = train_on_raw_and_quantized_data_params_fixture['train_pool']
    test_pool = train_on_raw_and_quantized_data_params_fixture['test_pool']
    train_quantized_pool = train_on_raw_and_quantized_data_params_fixture['train_quantized_pool']
    test_quantized_pool = train_on_raw_and_quantized_data_params_fixture['test_quantized_pool']
    params = train_on_raw_and_quantized_data_params_fixture['params']

    model = train(train_pool, params=params)
    model_fitted_with_quantized_pool = train(train_quantized_pool, params=params)

    predictions = model.predict(test_pool)
    predictions_with_quantized_pool = model_fitted_with_quantized_pool.predict(test_quantized_pool)
    assert n.all(predictions == predictions_with_quantized_pool)
//  [python]
def test_quantized_pool_train_predict(train_on_raw_and_quantized_data_params_fixture):
    train_pool = train_on_raw_and_quantized_data_params_fixture['train_pool']
    test_pool = train_on_raw_and_quantized_data_params_fixture['test_pool']
    train_quantized_pool = train_on_raw_and_quantized_data_params_fixture['train_quantized_pool']
    test_quantized_pool = train_on_raw_and_quantized_data_params_fixture['test_quantized_pool']
    params = train_on_raw_and_quantized_data_params_fixture['params']

    model = train(train_pool, params=params)
    model_fitted_with_quantized_pool = train(train_quantized_pool, params=params)

    predictions = model.predict(test_pool)
    predictions_with_quantized_pool = model_fitted_with_quantized_pool.predict(test_quantized_pool)
    assert np.all(predictions == predictions_with_quantized_pool)
//  [python]
def assert_sum_models_equal_sliced_copies(train, test, cd):
    train_pool = Pool(train, column_description=cd)
    test_pool = Pool(test, column_description=cd)
    iter_step = 10
    model_count = 2
    model = CatBoostClassifier(iterations=iter_step * model_count)
    model.fit(train_pool)

    truncated_copies = [model.copy() for _ in range(model_count)]
    for i, truncated_model in enumerate(truncated_copies):
        truncated_model.shrink(ntree_start=i * iter_step, ntree_end=(i + 1) * iter_step)

        pred_local_shrinked = truncated_model.predict(test_pool, prediction_type='RawFormulaVal')
        pred_local = model.predict(
            test_pool,
            prediction_type='RawFormulaVal',
            ntree_start=i * iter_step,
            ntree_end=(i + 1) * iter_step)

        assert n.all(pred_local_shrinked == pred_local)
        assert n.all(model.classes_ == truncated_model.classes_)

    weights = [1.0] * model_count
    merged_model = sum_models(truncated_copies, weights)
    pred = model.predict(test_pool, prediction_type='RawFormulaVal')
    merged_pred = merged_model.predict(test_pool, prediction_type='RawFormulaVal')

    assert n.all(pred == merged_pred)
    assert n.all(model.classes_ == merged_model.classes_)
//  [python]
def assert_sum_models_equal_sliced_copies(train, test, cd):
    train_pool = Pool(train, column_description=cd)
    test_pool = Pool(test, column_description=cd)
    iter_step = 10
    model_count = 2
    model = CatBoostClassifier(iterations=iter_step * model_count)
    model.fit(train_pool)

    truncated_copies = [model.copy() for _ in range(model_count)]
    for i, truncated_model in enumerate(truncated_copies):
        truncated_model.shrink(ntree_start=i * iter_step, ntree_end=(i + 1) * iter_step)

        pred_local_shrinked = truncated_model.predict(test_pool, prediction_type='RawFormulaVal')
        pred_local = model.predict(
            test_pool,
            prediction_type='RawFormulaVal',
            ntree_start=i * iter_step,
            ntree_end=(i + 1) * iter_step)

        assert np.all(pred_local_shrinked == pred_local)
        assert np.all(model.classes_ == truncated_model.classes_)

    weights = [1.0] * model_count
    merged_model = sum_models(truncated_copies, weights)
    pred = model.predict(test_pool, prediction_type='RawFormulaVal')
    merged_pred = merged_model.predict(test_pool, prediction_type='RawFormulaVal')

    assert np.all(pred == merged_pred)
    assert np.all(model.classes_ == merged_model.classes_)
//  [python]
def test_quantized_pool_get_feature_importance(models_trained_on_raw_and_quantized_data_fixture, pool_type, fstr_type):
    pool = models_trained_on_raw_and_quantized_data_fixture[pool_type + '_pool']
    quantized_pool = models_trained_on_raw_and_quantized_data_fixture[pool_type + '_quantized_pool']
    model = models_trained_on_raw_and_quantized_data_fixture['model']
    model_fitted_with_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['model_fitted_with_quantized_pool']

    fstr = model.get_feature_importance(data=pool, type=fstr_type)
    fstr_with_quantized_pool = \
        model_fitted_with_quantized_pool.get_feature_importance(data=quantized_pool, type=fstr_type)
    assert n.all(fstr == fstr_with_quantized_pool)
//  [python]
def test_quantized_pool_get_feature_importance(models_trained_on_raw_and_quantized_data_fixture, pool_type, fstr_type):
    pool = models_trained_on_raw_and_quantized_data_fixture[pool_type + '_pool']
    quantized_pool = models_trained_on_raw_and_quantized_data_fixture[pool_type + '_quantized_pool']
    model = models_trained_on_raw_and_quantized_data_fixture['model']
    model_fitted_with_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['model_fitted_with_quantized_pool']

    fstr = model.get_feature_importance(data=pool, type=fstr_type)
    fstr_with_quantized_pool = \
        model_fitted_with_quantized_pool.get_feature_importance(data=quantized_pool, type=fstr_type)
    assert np.all(fstr == fstr_with_quantized_pool)
//  [python]
def test_multiclass_train_on_constant_data(task_type):
    features = np.asarray(
        [[0.27290749, 0.63002519, 0., 0.38624339, 0.],
         [0.27290748, 0.63002519, 0., 0.38624339, 0.],
         [0.27290747, 0.63002519, 0., 0.38624339, 0.]]
    )
    classes = ['0', '1', '2']
    labels = np.asarray(classes)

    clf = CatBoostClassifier(
        iterations=2,
        loss_function='MultiClass'
    )

    model = clf.fit(features, labels)

    assert np.all(model.classes_ == classes)
    model.predict(features)
//  [python]
def test_quantized_pool_get_object_importance(models_trained_on_raw_and_quantized_data_fixture):
    train_pool = models_trained_on_raw_and_quantized_data_fixture['train_pool']
    test_pool = models_trained_on_raw_and_quantized_data_fixture['test_pool']
    train_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['train_quantized_pool']
    test_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['test_quantized_pool']
    model = models_trained_on_raw_and_quantized_data_fixture['model']
    model_fitted_with_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['model_fitted_with_quantized_pool']

    importance = model.get_object_importance(test_pool, train_pool)
    importance_with_quantized_pool = \
        model_fitted_with_quantized_pool.get_object_importance(test_quantized_pool, train_quantized_pool)
    assert n.all(n.array(importance) == n.array(importance_with_quantized_pool))
//  [python]
def test_quantized_pool_get_object_importance(models_trained_on_raw_and_quantized_data_fixture):
    train_pool = models_trained_on_raw_and_quantized_data_fixture['train_pool']
    test_pool = models_trained_on_raw_and_quantized_data_fixture['test_pool']
    train_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['train_quantized_pool']
    test_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['test_quantized_pool']
    model = models_trained_on_raw_and_quantized_data_fixture['model']
    model_fitted_with_quantized_pool = models_trained_on_raw_and_quantized_data_fixture['model_fitted_with_quantized_pool']

    importance = model.get_object_importance(test_pool, train_pool)
    importance_with_quantized_pool = \
        model_fitted_with_quantized_pool.get_object_importance(test_quantized_pool, train_quantized_pool)
    assert np.all(np.array(importance) == np.array(importance_with_quantized_pool))
//  [python]
def is_asc_sorted(arr):
    arr = np.asarray(arr)
    if len(arr) == 0:
        return True
    return np.all(arr[:-1] <= arr[1:])
//  [python]
def __init__(self, input_dim, alpha =1., beta=1., Z=None, name='SLVMPrior', **kw):
        super(SLVMPrior, self).__init__(name=name, **kw)
        self.input_dim = input_dim
        self.variance = 1.
        self.alpha = alpha
        self.beta = beta
        self.Z = Z
        if Z is not None:
            assert n.all(n.unique(Z)==n.array([0,1]))
//  [python]
def __init__(self, input_dim, alpha =1., beta=1., Z=None, name='SLVMPrior', **kw):
        super(SLVMPrior, self).__init__(name=name, **kw)
        self.input_dim = input_dim
        self.variance = 1.
        self.alpha = alpha
        self.beta = beta
        self.Z = Z
        if Z is not None:
            assert np.all(np.unique(Z)==np.array([0,1]))
//  [python]
def test_classes_attribute_binclass(label_type, loss_function):
    params = {'loss_function': loss_function, 'iterations': 2}

    if label_type == 'consecutive_integers':
        unique_labels = [0, 1]
    elif label_type == 'nonconsecutive_integers':
        unique_labels = [2, 5]
    elif label_type == 'string':
        unique_labels = ['class0', 'class1']
    elif label_type == 'float':
        unique_labels = [0.0, 0.1, 0.2, 0.5, 1.0]
        if loss_function == 'Logloss':
            params['target_border'] = 0.5

    features, labels = generate_random_labeled_dataset(n_samples=20, n_features=5, labels=unique_labels)

    model = CatBoostClassifier(**params)
    if (loss_function == 'CrossEntropy') and (label_type in ['nonconsecutive_integers', 'string']):
        # 'nonconsecutive_integers' because it is out of [0.0, 1.0] bounds
        # 'string' because CrossEntropy requires numerical target
        with pytest.raises(CatBoostError):
            model.fit(features, labels)
    else:
        model.fit(features, labels)

        if label_type == 'consecutive_integers':
            assert n.all(model.classes_ == [0, 1])
        elif label_type == 'nonconsecutive_integers':
            assert n.all(sorted(model.classes_) == [2, 5])
        elif label_type == 'string':
            assert n.all(model.classes_ == ['class0', 'class1'])
        elif label_type == 'float':
            assert n.all(model.classes_ == [0, 1])
//  [python]
def test_classes_attribute_binclass(label_type, loss_function):
    params = {'loss_function': loss_function, 'iterations': 2}

    if label_type == 'consecutive_integers':
        unique_labels = [0, 1]
    elif label_type == 'nonconsecutive_integers':
        unique_labels = [2, 5]
    elif label_type == 'string':
        unique_labels = ['class0', 'class1']
    elif label_type == 'float':
        unique_labels = [0.0, 0.1, 0.2, 0.5, 1.0]
        if loss_function == 'Logloss':
            params['target_border'] = 0.5

    features, labels = generate_random_labeled_dataset(n_samples=20, n_features=5, labels=unique_labels)

    model = CatBoostClassifier(**params)
    if (loss_function == 'CrossEntropy') and (label_type in ['nonconsecutive_integers', 'string']):
        # 'nonconsecutive_integers' because it is out of [0.0, 1.0] bounds
        # 'string' because CrossEntropy requires numerical target
        with pytest.raises(CatBoostError):
            model.fit(features, labels)
    else:
        model.fit(features, labels)

        if label_type == 'consecutive_integers':
            assert np.all(model.classes_ == [0, 1])
        elif label_type == 'nonconsecutive_integers':
            assert np.all(sorted(model.classes_) == [2, 5])
        elif label_type == 'string':
            assert np.all(model.classes_ == ['class0', 'class1'])
        elif label_type == 'float':
            assert np.all(model.classes_ == [0, 1])
//  [python]
def test_get_markers(self, marker_search, paris_clustering, datastore):
        precalc_markers = pd.read_csv(full_path("markers_cluster1.csv"), index_col=0)
        markers = datastore.get_markers(group_key="RNA_cluster", group_id=1)
        assert markers.feature_name.equals(precalc_markers.feature_name)
        diff = (markers.score - precalc_markers.score).values
        assert np.all(diff < 1e-3)
//  [python]
def test_classes_attribute_multiclass(label_type):
    params = {'loss_function': 'MultiClass', 'iterations': 2}

    if label_type == 'consecutive_integers':
        unique_labels = [0, 1, 2, 3]
    elif label_type == 'nonconsecutive_integers':
        unique_labels = [2, 5, 9, 11]
    elif label_type == 'string':
        unique_labels = ['class0', 'class1', 'class2', 'class3']
    elif label_type == 'float':
        unique_labels = [0.0, 0.1, 0.2, 0.5, 1.0]

    features, labels = generate_random_labeled_dataset(n_samples=20, n_features=5, labels=unique_labels)

    model = CatBoostClassifier(**params)
    model.fit(features, labels)

    if label_type == 'consecutive_integers':
        assert n.all(model.classes_ == [0, 1, 2, 3])
    elif label_type == 'nonconsecutive_integers':
        assert n.all(model.classes_ == [2, 5, 9, 11])
    elif label_type == 'string':
        assert n.all(sorted(model.classes_) == ['class0', 'class1', 'class2', 'class3'])
    elif label_type == 'float':
        assert n.allclose(sorted(model.classes_), [0, 0.1, 0.2, 0.5, 1])
//  [python]
def test_classes_attribute_multiclass(label_type):
    params = {'loss_function': 'MultiClass', 'iterations': 2}

    if label_type == 'consecutive_integers':
        unique_labels = [0, 1, 2, 3]
    elif label_type == 'nonconsecutive_integers':
        unique_labels = [2, 5, 9, 11]
    elif label_type == 'string':
        unique_labels = ['class0', 'class1', 'class2', 'class3']
    elif label_type == 'float':
        unique_labels = [0.0, 0.1, 0.2, 0.5, 1.0]

    features, labels = generate_random_labeled_dataset(n_samples=20, n_features=5, labels=unique_labels)

    model = CatBoostClassifier(**params)
    model.fit(features, labels)

    if label_type == 'consecutive_integers':
        assert np.all(model.classes_ == [0, 1, 2, 3])
    elif label_type == 'nonconsecutive_integers':
        assert np.all(model.classes_ == [2, 5, 9, 11])
    elif label_type == 'string':
        assert np.all(sorted(model.classes_) == ['class0', 'class1', 'class2', 'class3'])
    elif label_type == 'float':
        assert np.allclose(sorted(model.classes_), [0, 0.1, 0.2, 0.5, 1])
//  [python]
def take(
        self, indices: Sequence_[int], allow_fill: bool = False, fill_value: bool = None
    ) -> "PandasArrayExtensionArray":
        indices: np.ndarray = np.asarray(indices, dtype="int")
        if allow_fill:
            fill_value = (
                self.dtype.na_value
                if fill_value is None
                else np.asarray(fill_value, dtype=self.dtype.value_type)
            )
            mask = indices == -1
            if (indices < -1).any():
                raise ValueError(
                    "Invalid value in `indices`, must be all >= "
                    "-1 for `allow_fill` is True"
                )
            elif len(self) > 0:
                pass
            elif not np.alltrue(mask):
                raise IndexError(
                    "Invalid take for empty PandasArrayExtensionArray, must be all -1."
                )
            else:
                data = np.array(
                    [fill_value] * len(indices), dtype=self.dtype.value_type
                )
                return PandasArrayExtensionArray(data, copy=False)
        took = self._data.take(indices, axis=0)
        if allow_fill and mask.any():
            took[mask] = [fill_value] * np.sum(mask)
        return PandasArrayExtensionArray(took, copy=False)
//  [python]
def take(
        self, indices: Sequence_[int], allow_fill: bool = False, fill_value: bool = None
    ) -> "PandasArrayExtensionArray":
        indices: np.ndarray = np.asarray(indices, dtype="int")
        if allow_fill:
            fill_value = (
                self.dtype.na_value
                if fill_value is None
                else np.asarray(fill_value, dtype=self.dtype.value_type)
            )
            mask = indices == -1
            if (indices < -1).any():
                raise ValueError(
                    "Invalid value in `indices`, must be all >= "
                    "-1 for `allow_fill` is True"
                )
            elif len(self) > 0:
                pass
            elif not np.all(mask):
                raise IndexError(
                    "Invalid take for empty PandasArrayExtensionArray, must be all -1."
                )
            else:
                data = np.array(
                    [fill_value] * len(indices), dtype=self.dtype.value_type
                )
                return PandasArrayExtensionArray(data, copy=False)
        took = self._data.take(indices, axis=0)
        if allow_fill and mask.any():
            took[mask] = [fill_value] * np.sum(mask)
        return PandasArrayExtensionArray(took, copy=False)
//  [python]
def test_get_mapping_score(self, run_mapping, cell_attrs, datastore):
        scores = next(datastore.get_mapping_score(target_name="selfmap"))[1]
        diff = scores - cell_attrs["mapping_scores"].values
        assert n.all(diff < 1e-3)
//  [python]
def test_get_mapping_score(self, run_mapping, cell_attrs, datastore):
        scores = next(datastore.get_mapping_score(target_name="selfmap"))[1]
        diff = scores - cell_attrs["mapping_scores"].values
        assert np.all(diff < 1e-3)
//  [python]
def test_run_pseudotime_scoring(self, pseudotime_scoring, cell_attrs):
        diff = pseudotime_scoring - cell_attrs["RNA_pseudotime"].values
        assert np.all(diff < 1e-3)
//  [python]
def test_binclass_probability_threshold():
    # binary classification
    pool = Pool(TRAIN_FILE, column_description=CD_FILE)

    classifier = CatBoostClassifier(iterations=2)
    with pytest.raises(CatBoostError):
        classifier.set_probability_threshold(0.6)  # can't set before training
    with pytest.raises(CatBoostError):
        classifier.get_probability_threshold()  # can't get before training

    classifier.fit(pool)
    assert classifier.get_probability_threshold() == 0.5  # check default value

    classifier.set_probability_threshold(0.6)  # check set
    assert classifier.get_probability_threshold() == 0.6  # check get

    def check_predictions_with_threshold(classifier, threshold):
        proba = classifier.predict_proba(pool)[:, 1]
        pred = classifier.predict(pool).astype(int)
        if threshold < 0.5:
            assert np.any((proba > threshold) & (proba < 0.5))  # check for non-dummy test case
        elif threshold > 0.5:
            assert np.any((proba > 0.5) & (proba < threshold))  # check for non-dummy test case

        assert n.all(pred == (proba > threshold).astype(int))  # check if threshold is working

    check_predictions_with_threshold(classifier, 0.6)

    accuracy = classifier.score(pool)  # check if score function is working too
    pred = classifier.predict(pool).astype(int)
    assert np.allclose(accuracy, np.mean(pred == np.array(pool.get_label()).astype(int)))

    # change threshold
    classifier.set_probability_threshold(0.4)
    assert classifier.get_probability_threshold() == 0.4
    check_predictions_with_threshold(classifier, 0.4)

    # nullify it
    classifier.set_probability_threshold(None)
    assert classifier.get_probability_threshold() == 0.5
    check_predictions_with_threshold(classifier, 0.5)
//  [python]
def test_binclass_probability_threshold():
    # binary classification
    pool = Pool(TRAIN_FILE, column_description=CD_FILE)

    classifier = CatBoostClassifier(iterations=2)
    with pytest.raises(CatBoostError):
        classifier.set_probability_threshold(0.6)  # can't set before training
    with pytest.raises(CatBoostError):
        classifier.get_probability_threshold()  # can't get before training

    classifier.fit(pool)
    assert classifier.get_probability_threshold() == 0.5  # check default value

    classifier.set_probability_threshold(0.6)  # check set
    assert classifier.get_probability_threshold() == 0.6  # check get

    def check_predictions_with_threshold(classifier, threshold):
        proba = classifier.predict_proba(pool)[:, 1]
        pred = classifier.predict(pool).astype(int)
        if threshold < 0.5:
            assert np.any((proba > threshold) & (proba < 0.5))  # check for non-dummy test case
        elif threshold > 0.5:
            assert np.any((proba > 0.5) & (proba < threshold))  # check for non-dummy test case

        assert np.all(pred == (proba > threshold).astype(int))  # check if threshold is working

    check_predictions_with_threshold(classifier, 0.6)

    accuracy = classifier.score(pool)  # check if score function is working too
    pred = classifier.predict(pool).astype(int)
    assert np.allclose(accuracy, np.mean(pred == np.array(pool.get_label()).astype(int)))

    # change threshold
    classifier.set_probability_threshold(0.4)
    assert classifier.get_probability_threshold() == 0.4
    check_predictions_with_threshold(classifier, 0.4)

    # nullify it
    classifier.set_probability_threshold(None)
    assert classifier.get_probability_threshold() == 0.5
    check_predictions_with_threshold(classifier, 0.5)
//  [python]
def load_time_slides(hdf_file_path):
    """Loads timeslides from PyGRB output file as a dictionary"""
    hdf_file = h5py.File(hdf_file_path, 'r')
    ifos = extract_ifos(hdf_file_path)
    ids = numpy.arange(len(hdf_file[f'{ifos[0]}/search/time_slides']))
    time_slide_dict = {
        slide_id: {
            ifo: hdf_file[f'{ifo}/search/time_slides'][slide_id]
            for ifo in ifos}
        for slide_id in ids}

    # Check time_slide_ids are ordered correctly.
    if not (n.all(ids[1:] == n.array(ids[:-1])+1) and ids[0] == 0):
        err_msg = "time_slide_ids list should start at zero and increase by "
        err_msg += "one for every element"
        raise RuntimeError(err_msg)
    # Check that the zero-lag slide has time_slide_id == 0.
    if not n.all(n.array(list(time_slide_dict[0].values())) == 0):
        err_msg = "The slide with time_slide_id == 0 should be the "
        err_msg += "zero-lag-slide but it has non-zero slide values: "
        err_msg += f"{time_slide_dict[0]}."
        raise RuntimeError(err_msg)

    return time_slide_dict
//  [python]
def load_time_slides(hdf_file_path):
    """Loads timeslides from PyGRB output file as a dictionary"""
    hdf_file = h5py.File(hdf_file_path, 'r')
    ifos = extract_ifos(hdf_file_path)
    ids = numpy.arange(len(hdf_file[f'{ifos[0]}/search/time_slides']))
    time_slide_dict = {
        slide_id: {
            ifo: hdf_file[f'{ifo}/search/time_slides'][slide_id]
            for ifo in ifos}
        for slide_id in ids}

    # Check time_slide_ids are ordered correctly.
    if not (numpy.all(ids[1:] == numpy.array(ids[:-1])+1) and ids[0] == 0):
        err_msg = "time_slide_ids list should start at zero and increase by "
        err_msg += "one for every element"
        raise RuntimeError(err_msg)
    # Check that the zero-lag slide has time_slide_id == 0.
    if not numpy.all(numpy.array(list(time_slide_dict[0].values())) == 0):
        err_msg = "The slide with time_slide_id == 0 should be the "
        err_msg += "zero-lag-slide but it has non-zero slide values: "
        err_msg += f"{time_slide_dict[0]}."
        raise RuntimeError(err_msg)

    return time_slide_dict
//  [python]
def test_run_topacedo_sampler(self, cell_attrs, topacedo_sampler):
        assert np.all(topacedo_sampler == cell_attrs["RNA_sketched"])
//  [python]
def cameraInfoTest(data, gt_data):
    msg = ''
    if data.height != gt_data.height:
        msg = 'CameraInfo height is not matching'
        return False, msg
    if data.width != gt_data.width:
        msg = 'CameraInfo width is not matching'
        return False, msg
    if data.distortion_model != gt_data.distortion_model:
        msg = 'CameraInfo distortion_model is not matching'
        return False, msg
    if not np.all(np.equal(data.d , gt_data.d)):
        msg = 'CameraInfo d is not matching'
        return False, msg
    if len(data.k) != len(gt_data.k):
        msg = 'k sizes are not matching in extrinsics'
        return False, msg
    for count in range(len(data.k)):
        if abs(data.k[count] - gt_data.k[count]) > 1e-5:
            msg = 'k at %s are not matching values are %s and %s', (count, data.k[count] , gt_data.k[count])
            return False, msg

    if len(data.r) != len(gt_data.r):
        msg = 'r sizes are not matching in extrinsics'
        return False, msg
    for count in range(len(data.r)):
        if abs(data.r[count] - gt_data.r[count]) > 1e-5:
            msg = 'r at %s are not matching values are %s and %s', (count, data.r[count] , gt_data.r[count])
            return False, msg
    if len(data.p) != len(gt_data.p):
        msg = 'p sizes are not matching in extrinsics'
        return False, msg
    for count in range(len(data.p)):
        if abs(data.p[count] - gt_data.p[count]) > 1e-5:
            msg = 'p at %s are not matching values are %s and %s', (count, data.p[count] , gt_data.p[count])
            return False, msg

    if data.binning_x != gt_data.binning_x:
        msg = 'CameraInfo binning_x is not matching'
        return False, msg
    if data.binning_y != gt_data.binning_y:
        msg = 'CameraInfo binning_y is not matching'
        return False, msg
    if data.roi != gt_data.roi:
        msg = 'CameraInfo roi is not matching'
        return False, msg
    return True, ""
//  [python]
def test_run_pseudotime_aggregation(self, pseudotime_aggregation, datastore):
        precalc_values = np.load(full_path("aggregated_feat_idx.npy"))
        test_values = datastore.z.RNA.aggregated_I_I_RNA_pseudotime.feature_indices[:]
        assert np.all(precalc_values == test_values)

        precalc_values = np.load(full_path("aggregated_df_top_10.npy"))
        test_values = datastore.z.RNA.aggregated_I_I_RNA_pseudotime.data[:10]
        assert np.all(precalc_values == test_values)

        precalc_values = np.load(full_path("pseudotime_clusters.npy"))
        test_values = datastore.RNA.feats.fetch_all("pseudotime_clusters")
        assert np.all(precalc_values == test_values)
//  [python]
def _infer_time_units_from_diff(unique_timedeltas) -> str:
    unit_timedelta: Callable[[str], timedelta] | Callable[[str], np.timedelta64]
    zero_timedelta: timedelta | np.timedelta64
    if unique_timedeltas.dtype == np.dtype("O"):
        time_units = _NETCDF_TIME_UNITS_CFTIME
        unit_timedelta = _unit_timedelta_cftime
        zero_timedelta = timedelta(microseconds=0)
    else:
        time_units = _NETCDF_TIME_UNITS_NUMPY
        unit_timedelta = _unit_timedelta_numpy
        zero_timedelta = np.timedelta64(0, "ns")
    for time_unit in time_units:
        if n.all(unique_timedeltas % unit_timedelta(time_unit) == zero_timedelta):
            return time_unit
    return "seconds"
//  [python]
def _infer_time_units_from_diff(unique_timedeltas) -> str:
    unit_timedelta: Callable[[str], timedelta] | Callable[[str], np.timedelta64]
    zero_timedelta: timedelta | np.timedelta64
    if unique_timedeltas.dtype == np.dtype("O"):
        time_units = _NETCDF_TIME_UNITS_CFTIME
        unit_timedelta = _unit_timedelta_cftime
        zero_timedelta = timedelta(microseconds=0)
    else:
        time_units = _NETCDF_TIME_UNITS_NUMPY
        unit_timedelta = _unit_timedelta_numpy
        zero_timedelta = np.timedelta64(0, "ns")
    for time_unit in time_units:
        if np.all(unique_timedeltas % unit_timedelta(time_unit) == zero_timedelta):
            return time_unit
    return "seconds"
//  [python]
def __eq__(self, other: object) -> bool:
        if not isinstance(other, self.__class__):
            return False
        if len(self.f) != len(other.f):
            return False
        for prop in ['f','s','z0']:
            if not n.all(n.abs(getattr(self,prop)-getattr(other,prop))< ZERO):
                return False
        # if z0 is imaginary s_def is compared. If real of z0 is equal but s_def differs, networks are still equal
        if ((n.imag(self.z0) != 0).all()) or ((n.imag(other.z0) != 0).all()):
            if self.s_def == other.s_def:
                return True
            else:
                return n.allclose(self.z0.real, other.z0.real, atol = ZERO)
        else:
            return True
//  [python]
def __eq__(self, other: object) -> bool:
        if not isinstance(other, self.__class__):
            return False
        if len(self.f) != len(other.f):
            return False
        for prop in ['f','s','z0']:
            if not np.all(np.abs(getattr(self,prop)-getattr(other,prop))< ZERO):
                return False
        # if z0 is imaginary s_def is compared. If real of z0 is equal but s_def differs, networks are still equal
        if ((np.imag(self.z0) != 0).all()) or ((np.imag(other.z0) != 0).all()):
            if self.s_def == other.s_def:
                return True
            else:
                return np.allclose(self.z0.real, other.z0.real, atol = ZERO)
        else:
            return True
//  [python]
def MCMC(M,N,mu0=Bgmap().mu,prior=Bgmap(),nsamp=1000,nwalkers=20):
    """ Performs MCMC computation of likelihood distribution for the 
    background mapping between two frames.
    """
    import emcee

    def lnprob(P,M=M,N=N,prior=prior):
        """ Returns the log probability (\propto -0.5*chi^2) of the
        mapping parameter set P for mapping between two sets of objects
        M and N.
        """
        llik = -0.5 * np.sum( distance(M[i],N[i].transform(P))
                          for i in range(len(M)) )

        if n.all(n.isinf(n.diag(prior.sigma))):
            # De-facto uniform prior; don't bother computing prior llik.
            return llik
        else:
            return llik + prior.llik(P)

    ndim = 7
    p0 = [mu0+np.random.randn(ndim) for i in range(nwalkers)]
    
    sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, args=[M,N,prior])
    sampler.run_mcmc(p0, nsamp)

    return sampler
//  [python]
def MCMC(M,N,mu0=Bgmap().mu,prior=Bgmap(),nsamp=1000,nwalkers=20):
    """ Performs MCMC computation of likelihood distribution for the 
    background mapping between two frames.
    """
    import emcee

    def lnprob(P,M=M,N=N,prior=prior):
        """ Returns the log probability (\propto -0.5*chi^2) of the
        mapping parameter set P for mapping between two sets of objects
        M and N.
        """
        llik = -0.5 * np.sum( distance(M[i],N[i].transform(P))
                          for i in range(len(M)) )

        if np.all(np.isinf(np.diag(prior.sigma))):
            # De-facto uniform prior; don't bother computing prior llik.
            return llik
        else:
            return llik + prior.llik(P)

    ndim = 7
    p0 = [mu0+np.random.randn(ndim) for i in range(nwalkers)]
    
    sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, args=[M,N,prior])
    sampler.run_mcmc(p0, nsamp)

    return sampler
//  [python]
def test_binary_manual():
    """Test a binary threshold with manual threshold value"""
    numpy.random.seed(0)
    image = numpy.random.uniform(size=(20, 20))
    expected = image > 0.5
    workspace, module = make_workspace(image)
    module.threshold_scope.value = cellprofiler.modules.threshold.TS_GLOBAL
    module.global_operation.value = cellprofiler.modules.threshold.TM_MANUAL
    module.manual_threshold.value = 0.5
    module.run(workspace)
    output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert n.all(output.pixel_data == expected)
//  [python]
def test_binary_manual():
    """Test a binary threshold with manual threshold value"""
    numpy.random.seed(0)
    image = numpy.random.uniform(size=(20, 20))
    expected = image > 0.5
    workspace, module = make_workspace(image)
    module.threshold_scope.value = cellprofiler.modules.threshold.TS_GLOBAL
    module.global_operation.value = cellprofiler.modules.threshold.TM_MANUAL
    module.manual_threshold.value = 0.5
    module.run(workspace)
    output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert numpy.all(output.pixel_data == expected)
//  [python]
def test_binary_global():
    """Test a binary threshold with Otsu global method"""
    numpy.random.seed(0)
    image = numpy.random.uniform(size=(20, 20))
    threshold = skimage.filters.threshold_otsu(image)
    expected = image > threshold
    workspace, module = make_workspace(image)
    module.threshold_scope.value = cellprofiler.modules.threshold.TS_GLOBAL
    module.global_operation.value = centrosome.threshold.TM_OTSU
    module.run(workspace)
    output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert n.all(output.pixel_data == expected)
//  [python]
def test_binary_global():
    """Test a binary threshold with Otsu global method"""
    numpy.random.seed(0)
    image = numpy.random.uniform(size=(20, 20))
    threshold = skimage.filters.threshold_otsu(image)
    expected = image > threshold
    workspace, module = make_workspace(image)
    module.threshold_scope.value = cellprofiler.modules.threshold.TS_GLOBAL
    module.global_operation.value = centrosome.threshold.TM_OTSU
    module.run(workspace)
    output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert numpy.all(output.pixel_data == expected)
//  [python]
def test_binary_correction():
    """Test a binary threshold with a correction factor"""
    numpy.random.seed(0)
    image = numpy.random.uniform(size=(20, 20))
    threshold = skimage.filters.threshold_otsu(image) * 0.5
    expected = image > threshold
    workspace, module = make_workspace(image)
    module.threshold_scope.value = cellprofiler.modules.threshold.TS_GLOBAL
    module.global_operation.value = centrosome.threshold.TM_OTSU
    module.threshold_correction_factor.value = 0.5
    module.run(workspace)
    output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert n.all(output.pixel_data == expected)
//  [python]
def test_binary_correction():
    """Test a binary threshold with a correction factor"""
    numpy.random.seed(0)
    image = numpy.random.uniform(size=(20, 20))
    threshold = skimage.filters.threshold_otsu(image) * 0.5
    expected = image > threshold
    workspace, module = make_workspace(image)
    module.threshold_scope.value = cellprofiler.modules.threshold.TS_GLOBAL
    module.global_operation.value = centrosome.threshold.TM_OTSU
    module.threshold_correction_factor.value = 0.5
    module.run(workspace)
    output = workspace.image_set.get_image(OUTPUT_IMAGE_NAME)
    assert numpy.all(output.pixel_data == expected)