


"""simple docstring"""






import warnings

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.metrics import pairwise_distances

warnings.filterwarnings("""ignore""")

UpperCamelCase__							:Optional[int]       =  """K-MEANS-CLUST/ """





def 							A_					(   snake_case__					,				snake_case__					,				snake_case__=None		)				->     Any:
			if seed is not None:  # useful for obtaining consistent results
						np.random.seed(snake_case__		)
			_UpperCamelCase				:List[Any]				    =  data.shape[0]  # number of data points

			# Pick K indices from range [0, N).
			_UpperCamelCase				:List[str]				    =  np.random.randint(0					,				snake_case__					,				snake_case__		)

			# Keep centroids as dense format, as many entries will be nonzero due to averaging.
			# As long as at least one document in a cluster contains a word,
			# it will carry a nonzero weight in the TF-IDF vector of the centroid.
			_UpperCamelCase				:List[str]				    =  data[rand_indices, :]

			return centroids





def 							A_					(   snake_case__					,				snake_case__		)				->     Optional[int]:
			return pairwise_distances(snake_case__					,				snake_case__					,				metric='''euclidean'''		)





def 							A_					(   snake_case__					,				snake_case__		)				->     Optional[Any]:
			# Compute distances between each data point and the set of centroids:
			# Fill in the blank (RHS only)
			_UpperCamelCase				:Optional[Any]				    =  centroid_pairwise_dist(snake_case__					,				snake_case__		)

			# Compute cluster assignments for each data point:
			# Fill in the blank (RHS only)
			_UpperCamelCase				:List[str]				    =  np.argmin(snake_case__					,				axis=1		)

			return cluster_assignment





def 							A_					(   snake_case__					,				snake_case__					,				snake_case__		)				->     str:
			_UpperCamelCase				:Tuple				    =  []
			for i in range(snake_case__		):
						# Select all data points that belong to cluster i. Fill in the blank (RHS only)
						_UpperCamelCase				:int				    =  data[cluster_assignment == i]
						# Compute the mean of the data points. Fill in the blank (RHS only)
						_UpperCamelCase				:int				    =  member_data_points.mean(axis=0		)
						new_centroids.append(snake_case__		)
			_UpperCamelCase				:int				    =  np.array(snake_case__		)

			return new_centroids





def 							A_					(   snake_case__					,				snake_case__					,				snake_case__					,				snake_case__		)				->     List[str]:
			_UpperCamelCase				:Optional[Any]				    =  0.0
			for i in range(snake_case__		):
						# Select all data points that belong to cluster i. Fill in the blank (RHS only)
						_UpperCamelCase				:Union[str, Any]				    =  data[cluster_assignment == i, :]

						if member_data_points.shape[0] > 0:  # check if i-th cluster is non-empty
									# Compute distances from centroid to data points (RHS only)
									_UpperCamelCase				:Union[str, Any]				    =  pairwise_distances(
									    snake_case__					,				[centroids[i]]					,				metric='''euclidean'''		)
									_UpperCamelCase				:Any				    =  distances**2
									heterogeneity += np.sum(snake_case__		)

			return heterogeneity





def 							A_					(   snake_case__					,				snake_case__		)				->     Union[str, Any]:
			plt.figure(figsize=(7, 4)		)
			plt.plot(snake_case__					,				linewidth=4		)
			plt.xlabel('''# Iterations'''		)
			plt.ylabel('''Heterogeneity'''		)
			plt.title(f"Heterogeneity of clustering over time, K={k:d}"		)
			plt.rcParams.update({'''font.size''': 16}		)
			plt.show()





def 							A_					(   snake_case__					,				snake_case__					,				snake_case__					,				snake_case__=5_00					,				snake_case__=None					,				snake_case__=False		)				->     List[str]:
			_UpperCamelCase				:Tuple				    =  initial_centroids[:]
			_UpperCamelCase				:Optional[Any]				    =  None

			for itr in range(snake_case__		):
						if verbose:
									print(snake_case__					,				end=''''''		)

						# 1. Make cluster assignments using nearest centroids
						_UpperCamelCase				:Dict				    =  assign_clusters(snake_case__					,				snake_case__		)

						# 2. Compute a new centroid for each of the k clusters, averaging all data
						#    points assigned to that cluster.
						_UpperCamelCase				:str				    =  revise_centroids(snake_case__					,				snake_case__					,				snake_case__		)

						# Check for convergence: if none of the assignments changed, stop
						if (
						    prev_cluster_assignment is not None
						    and (prev_cluster_assignment == cluster_assignment).all()
						):
									break

						# Print number of new assignments
						if prev_cluster_assignment is not None:
									_UpperCamelCase				:str				    =  np.sum(prev_cluster_assignment != cluster_assignment		)
									if verbose:
												print(
												    f"    {num_changed:5d} elements changed their cluster assignment."		)

        # Record heterogeneity convergence metric
						if record_heterogeneity is not None:
									# YOUR CODE HERE
									_UpperCamelCase				:List[str]				    =  compute_heterogeneity(snake_case__					,				snake_case__					,				snake_case__					,				snake_case__		)
									record_heterogeneity.append(snake_case__		)

						_UpperCamelCase				:Optional[Any]				    =  cluster_assignment[:]

			return centroids, cluster_assignment


# Mock test below
if False:  # change to true to run this test case.
					from sklearn import datasets as ds

					UpperCamelCase__							:int       =  ds.load_iris()
					UpperCamelCase__							:List[str]       =  3
					UpperCamelCase__							:Dict       =  []
					UpperCamelCase__							:Dict       =  get_initial_centroids(dataset["""data"""], k, seed=0)
					UpperCamelCase__      , UpperCamelCase__							:List[Any]       =  kmeans(
					    dataset["""data"""],
					    k,
					    initial_centroids,
					    maxiter=400,
					    record_heterogeneity=heterogeneity,
					    verbose=True,
					)
					plot_heterogeneity(heterogeneity, k)





def 							A_					(   snake_case__					,				snake_case__					,				snake_case__=None		)				->     pd.DataFrame:
			# Fill missing values with given rules
			if fill_missing_report:
						_UpperCamelCase				:Dict				    =  df.fillna(value=snake_case__		)
			_UpperCamelCase				:Union[str, Any]				    =  1
			_UpperCamelCase				:Dict				    =  df.select_dtypes(np.number		).columns
			_UpperCamelCase				:Any				    =  (
			    df.groupby(['''Cluster''']		)[  # construct report dataframe
			        numeric_cols
			    ]  # group by cluster number
			    .agg(
			        [
			            ('''sum''', np.sum),
			            ('''mean_with_zeros''', lambda snake_case__		: np.mean(np.nan_to_num(snake_case__		)		)),
			            ('''mean_without_zeros''', lambda snake_case__		: x.replace(0					,				np.NaN		).mean()),
			            (
			                '''mean_25-75''',
			                lambda snake_case__		: np.mean(
			                    np.nan_to_num(
			                        sorted(snake_case__		)[
			                            round(len(snake_case__		) * 25 / 1_00		) : round(len(snake_case__		) * 75 / 1_00		)
			                        ]		)		),
			            ),
			            ('''mean_with_na''', np.mean),
			            ('''min''', lambda snake_case__		: x.min()),
			            ('''5%''', lambda snake_case__		: x.quantile(0.05		)),
			            ('''25%''', lambda snake_case__		: x.quantile(0.25		)),
			            ('''50%''', lambda snake_case__		: x.quantile(0.50		)),
			            ('''75%''', lambda snake_case__		: x.quantile(0.75		)),
			            ('''95%''', lambda snake_case__		: x.quantile(0.95		)),
			            ('''max''', lambda snake_case__		: x.max()),
			            ('''count''', lambda snake_case__		: x.count()),
			            ('''stdev''', lambda snake_case__		: x.std()),
			            ('''mode''', lambda snake_case__		: x.mode()[0]),
			            ('''median''', lambda snake_case__		: x.median()),
			            ('''# > 0''', lambda snake_case__		: (x > 0).sum()),
			        ]		)
			    .T.reset_index()
			    .rename(index=snake_case__					,				columns={'''level_0''': '''Features''', '''level_1''': '''Type'''}		)
			)  # rename columns
			# calculate the size of cluster(count of clientID's)
			_UpperCamelCase				:List[str]				    =  report[
			    (report['''Features'''] == '''dummy''') & (report['''Type'''] == '''count''')
			].copy()  # avoid SettingWithCopyWarning
			_UpperCamelCase				:Union[str, Any]				    =  (
			    '''ClusterSize'''  # rename created cluster df to match report column names
			)
			_UpperCamelCase				:int				    =  '''# of Customers'''
			_UpperCamelCase				:List[str]				    =  pd.DataFrame(
			    clustersize.iloc[:, 2:].values
			    / clustersize.iloc[:, 2:].values.sum()		)
			_UpperCamelCase				:Union[str, Any]				    =  '''% of Customers'''  # rename created cluster df to match report column names
			_UpperCamelCase				:Union[str, Any]				    =  '''ClusterProportion'''
			_UpperCamelCase				:int				    =  clusterproportion.columns.tolist()
			_UpperCamelCase				:Tuple				    =  cols[-2:] + cols[:-2]
			_UpperCamelCase				:Tuple				    =  clusterproportion[cols]  # rearrange columns to match report
			_UpperCamelCase				:Dict				    =  report.columns
			_UpperCamelCase				:List[str]				    =  pd.DataFrame(
			    abs(
			        report[report['''Type'''] == '''count'''].iloc[:, 2:].values
			        - clustersize.iloc[:, 2:].values		)		)  # generating df with count of nan values
			_UpperCamelCase				:Any				    =  0
			_UpperCamelCase				:Optional[int]				    =  '''# of nan'''
			_UpperCamelCase				:Optional[Any]				    =  report[
			    report['''Type'''] == '''count'''
			].Features.tolist()  # filling values in order to match report
			_UpperCamelCase				:Tuple				    =  a.columns.tolist()
			_UpperCamelCase				:str				    =  cols[-2:] + cols[:-2]
			_UpperCamelCase				:str				    =  a[cols]  # rearrange columns to match report
			_UpperCamelCase				:List[str]				    =  report.columns  # rename columns to match report
			_UpperCamelCase				:Optional[Any]				    =  report.drop(
			    report[report.Type == '''count'''].index		)  # drop count values except cluster size
			_UpperCamelCase				:Union[str, Any]				    =  pd.concat(
			    [report, a, clustersize, clusterproportion]					,				axis=0		)  # concat report with clustert size and nan values
			_UpperCamelCase				:Tuple				    =  report['''Features'''].isin(snake_case__		)
			_UpperCamelCase				:int				    =  report.columns.tolist()
			_UpperCamelCase				:str				    =  cols[0:2] + cols[-1:] + cols[2:-1]
			_UpperCamelCase				:List[Any]				    =  report[cols]
			_UpperCamelCase				:int				    =  {
			    '''ClusterSize''': 9,
			    '''ClusterProportion''': 8,
			    '''mean_with_zeros''': 7,
			    '''mean_with_na''': 6,
			    '''max''': 5,
			    '''50%''': 4,
			    '''min''': 3,
			    '''25%''': 2,
			    '''75%''': 1,
			    '''# of nan''': 0,
			    '''# > 0''': -1,
			    '''sum_with_na''': -2,
			}
			_UpperCamelCase				:str				    =  (
			    report.assign(
			        Sortera=lambda snake_case__		: x.Type.map(snake_case__		)					,				Sortera=lambda snake_case__		: list(reversed(range(len(snake_case__		)		)		)		)					,				)
			    .sort_values(['''Sorter1''', '''Mark''', '''Sorter2''']					,				ascending=snake_case__		)
			    .drop(['''Sorter1''', '''Sorter2''']					,				axis=1		)
			)
			_UpperCamelCase				:Union[str, Any]				    =  ''''''
			_UpperCamelCase				:Dict				    =  report.reset_index()
			_UpperCamelCase				:Dict				    =  report.drop(columns=['''index''']		)
			return report


if __name__ == "__main__":
					import doctest

					doctest.testmod()





"""simple docstring"""






import numpy as np
from cva import COLOR_BGR2GRAY, cvtColor, imread, imshow, waitKey

from digital_image_processing.filters.convolve import img_convolve





def 							A_					(   snake_case__		)				->     str:
			_UpperCamelCase				:List[Any]				    =  np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]		)
			_UpperCamelCase				:Dict				    =  np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]		)

			_UpperCamelCase				:List[str]				    =  np.abs(img_convolve(snake_case__					,				snake_case__		)		)
			_UpperCamelCase				:Dict				    =  np.abs(img_convolve(snake_case__					,				snake_case__		)		)
			# modify the pix within [0, 255]
			_UpperCamelCase				:List[Any]				    =  dst_x * 2_55 / np.max(snake_case__		)
			_UpperCamelCase				:Tuple				    =  dst_y * 2_55 / np.max(snake_case__		)

			_UpperCamelCase				:Tuple				    =  np.sqrt((np.square(snake_case__		)) + (np.square(snake_case__		))		)
			_UpperCamelCase				:Any				    =  dst_xy * 2_55 / np.max(snake_case__		)
			_UpperCamelCase				:Optional[int]				    =  dst_xy.astype(np.uinta		)

			_UpperCamelCase				:str				    =  np.arctana(snake_case__					,				snake_case__		)
			return dst, theta


if __name__ == "__main__":
					# read original image
					UpperCamelCase__							:List[str]       =  imread("""../image_data/lena.jpg""")
					# turn image in gray scale value
					UpperCamelCase__							:Union[str, Any]       =  cvtColor(img, COLOR_BGR2GRAY)

					UpperCamelCase__      , UpperCamelCase__							:Optional[int]       =  sobel_filter(gray)

					# show result images
					imshow("""sobel filter""", sobel_grad)
					imshow("""sobel theta""", sobel_theta)
					waitKey(0)

