Project: s41467-024-47334-0 | Function: fit (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Semi-supervised K-means clustering algorithm implementation with constrained initialization, alternating between E-step (assignment) and M-step (centroid update) with convergence criteria

**KEY TERMS:** {
  "labels_initial_": "initial semi-supervised labels",
  "mask": "unlabeled data points mask",
  "cluster_centers_": "centroid positions",
  "_e_step": "expectation step - point assignment",
  "_m_step": "maximization step - centroid update"
}

**CONTEXT CODE:** 

import numpy as np
from sklearn.base import BaseEstimator
from sklearn.metrics.pairwise import euclidean_distances
class ssKMeans(BaseEstimator):

    def __init__(self, k, max_iter=10000, random_state=0, tol=1e-10):
        self.k = k
        self.max_iter = max_iter
        self.random_state = random_state
        self.tol = tol

    def _e_step(self, X):
        
        
        temp = euclidean_distances(X, self.cluster_centers_,
                                 squared=True).argmin(axis=1)
        self.labels_ = np.copy(self.labels_initial_)
        self.labels_[self.mask] = temp[self.mask]

               

    def _average(self, X):
        return X.mean(axis=0)

    def _m_step(self, X):
        X_center = None
        for center_id in range(self.k):
            center_mask = self.labels_ == center_id
            if not np.any(center_mask):
                # The centroid of empty clusters is set to the center of
                # everything
                if X_center is None:
                    X_center = self._average(X)
                self.cluster_centers_[center_id] = X_center
            else:
                self.cluster_centers_[center_id] =                     self._average(X[center_mask])

    def fit(self, X, centroids, assigned_centroids):
        raise NotImplementedError("This function is intentionally masked for testing purposes.")



Complete the function implementation replacing "raise NotImplementedError".