{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install opencv-python==4.6.0.66\n!pip install tqdm==4.64.0\n!pip install numpy==1.23.1\n!pip install pandas==1.4.3\n!pip install seaborn==0.11.2\n!pip install matplotlib==3.5.2\n!pip install torch==1.12.1\n!pip install IPython==8.4.0","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-09-01T08:37:00.988774Z","iopub.execute_input":"2022-09-01T08:37:00.989492Z","iopub.status.idle":"2022-09-01T08:39:38.712279Z","shell.execute_reply.started":"2022-09-01T08:37:00.989357Z","shell.execute_reply":"2022-09-01T08:39:38.710716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Functions","metadata":{}},{"cell_type":"code","source":"def get_image_title(image_row):\n    \"\"\" Return a title from the information contained in a lia pandas Dataframe row\n\n    Args:\n        image_row(pandas.core.series.Series)\n\n    Return:\n        (str): \"ImageID | Organ | Sex | Age\"\n    \"\"\"\n    return \"%s | %s | %s | %s\" % (image_row[\"id\"], image_row[\"organ\"], image_row[\"sex\"], image_row[\"age\"])\n\n\ndef seed_everything(seed):\n    \"\"\" Initialize the random number generator.\n    Sets a seed for each module used which allows to have the same results during the iterations\n\n    Args:\n        seed (int):\n    \"\"\"\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\n    # the following line gives ~10% speedup\n    # but may lead to some stochasticity in the results\n    torch.backends.cudnn.benchmark = True\n\n\n\ndef mask2rle(img):\n    \"\"\" Method taken from : https://www.kaggle.com/paulorzp/rle-functions-run-length-encode-decode\n    Convert Mask format (Numpy image) to RLE (sting)\n\n    Args:\n        img (numpy.array): 1 - mask, 0 - background\n\n    Return:\n        (str) run length as string formated\n    \"\"\"\n    pixels = img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\n\ndef rle2mask(mask_rle, shape=(1600, 256)):\n    \"\"\" Method taken from : https://www.kaggle.com/paulorzp/rle-functions-run-length-encode-decode\n    Convert RLE format (sting) to mask (Numpy image)\n\n    Args:\n        mask_rle (str): run-length as string formated (start length)\n        shape (int, int): (width,height) of array to return\n\n    Return:\n         (numpy.array): 1 - mask, 0 - background\n    \"\"\"\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0] * shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T\n\n\ndef enhancement_image(image):\n    \"\"\" Method inspired by : https://stackoverflow.com/questions/39308030/how-do-i-increase-the-contrast-of-an-image-in-python-opencv\n\n    Enhance image contrast using LAB color space methodes\n\n    Args:\n        image (numpy.ndarray): image to improve\n\n    Return:\n        (numpy.ndarray): image improve\n    \"\"\"\n    sample = image.copy()\n    lab = cv2.cvtColor(sample, cv2.COLOR_BGR2LAB)\n    l_channel, a, b = cv2.split(lab)\n    # Applying CLAHE to L-channel\n    # feel free to try different values for the limit and grid size:\n    clahe = cv2.createCLAHE(clipLimit=5.0, tileGridSize=(12, 12))\n    cl = clahe.apply(l_channel)\n\n    # merge the CLAHE enhanced L-channel with the a and b channel\n    limg = cv2.merge((cl, a, b))\n\n    # Converting image from LAB Color model to BGR color space\n    enhanced_img = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)\n\n    return enhanced_img\n\ndef denormalize_image(image_tensor):\n    \"\"\" Reverses the normalization operation ( torch.nn.functional.normalize(mean, std) )\n\n    Args:\n        image_tensor (torch.tensor)\n\n    Return:\n        (numpy.array): denormalize image\n    \"\"\"\n    image = image_tensor.numpy().transpose((1, 2, 0))\n    image = std * image + mean\n    image = np.clip(image, 0, 1)\n\n    return image\n\ndef read_image(image_path, enhancement=False):\n    \"\"\" Read the image from the location where the file is located\n\n    Args:\n        image_path (str): the path to the picture\n        enhancement (boolean): Optional. if True improve the image quality\n\n    Return:\n        (numpy.ndarray): the image\n    \"\"\"\n    image = cv2.imread(image_path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n    if enhancement:\n        image = enhancement_image(image)\n\n    return image\n\ndef read_mask(rle, image_shape):\n    \"\"\" Convert RLE to mask\n\n    Args:\n        rle (str): run-length as string formated (start length)\n        image_shape  (int, int): (width,height) of array to return\n\n    Return:\n        (numpy.array): 1 - mask, 0 - background\n    \"\"\"\n    mask = rle2mask(mask_rle=rle,\n                    shape=image_shape)\n\n    return mask\n\n\ndef plot_result(result_dict, title, xlabel, ylabel):\n    \"\"\" Displays with to the matplotlib module, the evolution of the values contained in the dictionary result_dict\n    The key will be used as legend\n\n    Args:\n        result_dict (dict):\n            Example {\"value 1\" : [0, 2, 4, 6]}\n        title (str): table title\n        xlabel (str):\n        ylabel (str):\n    \"\"\"\n    plt.figure(figsize=(8, 6))\n\n    for key, values in result_dict.items():\n        if isinstance(values[0], torch.Tensor):\n            values = [value.cpu() for value in values]\n\n        plt.plot(values, label=key)\n\n    plt.title(title)\n    plt.xlabel(xlabel)\n    plt.ylabel(ylabel)\n\n    plt.legend(loc=\"best\")\n\n    plt.show()\n\n\ndef show_images(images, masks, title):\n    \"\"\" Displays a group of 3 images on 2 lines\n    on the top line the image is displayed, on the bottom line the image in background with transparent mask on top\n\n    Args:\n        images (list(torch.tensor)): list of image in form of tensor\n        masks (list(torch.tensor)): list of image in form of tensor\n        title (str):\n    \"\"\"\n    fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(14, 9))\n    plt.suptitle(title, fontsize=16)\n\n    for index, (image, mask) in enumerate(zip(images, masks)):\n        image = denormalize_image(image)\n        mask = mask.squeeze().numpy()\n\n        # Show  Image\n        ax = axs[0][index]\n        ax.imshow(image)\n        ax.set_axis_off()\n\n        # Show Image + Mask\n        ax = axs[1][index]\n\n        ax.imshow(image)\n        ax.imshow(mask, cmap='seismic', alpha=0.4)\n        ax.set_axis_off()\n\n    plt.tight_layout()\n    plt.show()\n\n\ndef show_image_enhancement(image_row):\n    \"\"\" Displays the original image on the left, and the Enhanced Image on right\n    \n    Args:\n        image_row(pandas.core.series.Series)\n    \"\"\"\n    img = read_image(image_row[\"image_path\"])\n    enhanced_img = read_image(image_row[\"image_path\"], enhancement=True)\n\n    fig, axs = plt.subplots(ncols=2, figsize=(12, 6))\n    plt.suptitle(get_image_title(image_row), fontsize=16)\n\n    axs[0].set_title(\"Original Image\")\n    axs[0].imshow(img)\n\n    axs[1].set_title(\"Enhanced Image\")\n    axs[1].imshow(enhanced_img)\n\n    for ax in axs:\n        ax.set_axis_off()\n\n    plt.tight_layout()\n\n    plt.show()\n\n\ndef show_image_mask(image_row):\n    \"\"\" From a row of a pandas dataFrame show 3 image\n    1st image is the original image, 2nd image is the mask\n    and the 3rd is the image in background with transparent mask on top\n\n    Args:\n        image_row(pandas.core.series.Series)\n    \"\"\"\n    img = read_image(image_row[\"image_path\"])\n    mask = read_mask(rle=image_row[\"rle\"], \n                    image_shape=(image_row[\"img_width\"], image_row[\"img_height\"]))\n    \n    fig, axs = plt.subplots(ncols=3, figsize=(14, 6))\n    plt.suptitle(get_image_title(image_row), fontsize=16)\n\n    axs[0].set_title(\"Original Image\")\n    axs[0].imshow(img)\n\n    axs[1].set_title(\"Mask\")\n    axs[1].imshow(mask, cmap=\"seismic\")\n\n    axs[2].set_title(\"Image + Mask\")\n    axs[2].imshow(img)\n    axs[2].imshow(mask, cmap='seismic', alpha=0.4)\n\n    for ax in axs:\n        ax.set_axis_off()\n    plt.tight_layout()\n\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:38.715799Z","iopub.execute_input":"2022-09-01T08:39:38.716201Z","iopub.status.idle":"2022-09-01T08:39:38.756928Z","shell.execute_reply.started":"2022-09-01T08:39:38.716157Z","shell.execute_reply":"2022-09-01T08:39:38.755809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nfrom glob import glob\nfrom tqdm import tqdm\n\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\nfrom IPython.display import display\n\nplt.rcParams.update({'font.size': 15})","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-09-01T08:39:38.758543Z","iopub.execute_input":"2022-09-01T08:39:38.759022Z","iopub.status.idle":"2022-09-01T08:39:39.519772Z","shell.execute_reply.started":"2022-09-01T08:39:38.758974Z","shell.execute_reply":"2022-09-01T08:39:39.518737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_base_path = os.path.join(\"..\", \"input\",\"hubmap-organ-segmentation\")\n\ntrain_df = pd.read_csv(os.path.join(input_base_path, \"train.csv\"))\ntest_df = pd.read_csv(os.path.join(input_base_path, \"test.csv\"))\n\ndisplay(train_df.head())\ndisplay(test_df.head())","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:39.522086Z","iopub.execute_input":"2022-09-01T08:39:39.522458Z","iopub.status.idle":"2022-09-01T08:39:39.864363Z","shell.execute_reply.started":"2022-09-01T08:39:39.522426Z","shell.execute_reply":"2022-09-01T08:39:39.863221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Cleaning Data & Feature engineering**","metadata":{}},{"cell_type":"markdown","source":"## Find and store image and annotation path","metadata":{}},{"cell_type":"code","source":"folder_ext_list = [(\"train_images\", \"*.tiff\"),\n                    (\"test_images\", \"*.tiff\"),\n                    (\"train_annotations\", \"*.json\")]\n\ndata_dict = {} # { \"train_images\" : { imageID :  image Path, ...},\n                #  \"test_image\" : { imageID :  image Path, ...},\n                #  \"train_annotations\" : { imageID :  image Path, ...},}\n\n\nfor folder_name, extension in folder_ext_list:\n    folder_path = os.path.join(input_base_path, folder_name, extension)\n    print(\" Find File in %s\" % folder_path)\n    \n    file_list = glob(folder_path, recursive=True)\n    \n    file_path_dict = {} # { imageID : image Path}\n    data_dict[folder_name] = file_path_dict\n    \n    for file_path in file_list:\n        base_name = os.path.basename(file_path) \n        _id = os.path.splitext(base_name)[0]\n        _id = int(_id)\n        \n        file_path_dict[_id] = file_path","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:39.866036Z","iopub.execute_input":"2022-09-01T08:39:39.866384Z","iopub.status.idle":"2022-09-01T08:39:39.996666Z","shell.execute_reply.started":"2022-09-01T08:39:39.866353Z","shell.execute_reply":"2022-09-01T08:39:39.995574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df[\"image_path\"] = train_df[\"id\"].apply(lambda x : data_dict[\"train_images\"][x])\ntrain_df[\"info_path\"] = train_df[\"id\"].apply(lambda x : data_dict[\"train_annotations\"][x])\n\ntest_df[\"image_path\"] = test_df[\"id\"].apply(lambda x : data_dict[\"test_images\"][x])\n\ndisplay(train_df.head(2))\nprint(\"DataFrame Shape : %s\" % list(train_df.shape))\n\ndisplay(test_df.head())\nprint(\"DataFrame Shape : %s\" % list(test_df.shape))","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:39.999938Z","iopub.execute_input":"2022-09-01T08:39:40.000674Z","iopub.status.idle":"2022-09-01T08:39:40.038525Z","shell.execute_reply.started":"2022-09-01T08:39:40.000637Z","shell.execute_reply":"2022-09-01T08:39:40.037668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Saving DataFrames","metadata":{}},{"cell_type":"code","source":"output_base_path = os.path.join(\"..\", \"working\")\n\ntrain_path = os.path.join(output_base_path, \"clean_train.csv\")\ntest_path = os.path.join(output_base_path, \"clean_test.csv\")\n\n\ntrain_df.to_csv(train_path, index=False)\ntest_df.to_csv(test_path, index=False)","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:40.039754Z","iopub.execute_input":"2022-09-01T08:39:40.040612Z","iopub.status.idle":"2022-09-01T08:39:40.354302Z","shell.execute_reply.started":"2022-09-01T08:39:40.040580Z","shell.execute_reply":"2022-09-01T08:39:40.353319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Exploratory analysis","metadata":{}},{"cell_type":"code","source":"sns.countplot(data=train_df, x=\"data_source\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:40.355674Z","iopub.execute_input":"2022-09-01T08:39:40.356337Z","iopub.status.idle":"2022-09-01T08:39:40.535097Z","shell.execute_reply.started":"2022-09-01T08:39:40.356283Z","shell.execute_reply":"2022-09-01T08:39:40.534290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(6, 6))\n\ntrain_df[[\"sex\"]].value_counts().plot.pie(autopct='%1.1f%%', ylabel=\"sex\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:40.536576Z","iopub.execute_input":"2022-09-01T08:39:40.537186Z","iopub.status.idle":"2022-09-01T08:39:40.679212Z","shell.execute_reply.started":"2022-09-01T08:39:40.537152Z","shell.execute_reply":"2022-09-01T08:39:40.677695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 6))\n\nsns.histplot(data=train_df, x=\"organ\", hue=\"sex\", multiple=\"stack\")\n\nax.set_axisbelow(True)\nplt.grid()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:40.685851Z","iopub.execute_input":"2022-09-01T08:39:40.687017Z","iopub.status.idle":"2022-09-01T08:39:40.995756Z","shell.execute_reply.started":"2022-09-01T08:39:40.686951Z","shell.execute_reply":"2022-09-01T08:39:40.994607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(12, 6))\n\nsns.histplot(data=train_df, x=\"age\", hue=\"sex\", multiple=\"stack\")\n\nax.set_axisbelow(True)\nplt.grid()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:40.998455Z","iopub.execute_input":"2022-09-01T08:39:40.999221Z","iopub.status.idle":"2022-09-01T08:39:41.339609Z","shell.execute_reply.started":"2022-09-01T08:39:40.999172Z","shell.execute_reply":"2022-09-01T08:39:41.338467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display(train_df[\"tissue_thickness\"].describe())","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:41.341457Z","iopub.execute_input":"2022-09-01T08:39:41.342173Z","iopub.status.idle":"2022-09-01T08:39:41.355126Z","shell.execute_reply.started":"2022-09-01T08:39:41.342103Z","shell.execute_reply":"2022-09-01T08:39:41.353953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display(train_df[[\"img_height\", \"img_width\", \"pixel_size\"]].describe())","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:41.356904Z","iopub.execute_input":"2022-09-01T08:39:41.357876Z","iopub.status.idle":"2022-09-01T08:39:41.383611Z","shell.execute_reply.started":"2022-09-01T08:39:41.357843Z","shell.execute_reply":"2022-09-01T08:39:41.382645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Image analysis\nREF : https://www.kaggle.com/code/nghihuynh/hubmap-hpa-exploratory-data-analysis","metadata":{}},{"cell_type":"markdown","source":"### Analysis Mask","metadata":{}},{"cell_type":"code","source":"first_row = train_df.iloc[1]\n\nimg = cv2.imread(first_row[\"image_path\"])\n\nmask = rle2mask(mask_rle=first_row[\"rle\"], shape=(img.shape[0], img.shape[1]))\nprint(mask.shape)","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:41.386166Z","iopub.execute_input":"2022-09-01T08:39:41.386660Z","iopub.status.idle":"2022-09-01T08:39:41.869744Z","shell.execute_reply.started":"2022-09-01T08:39:41.386609Z","shell.execute_reply":"2022-09-01T08:39:41.868627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_image_mask(train_df.iloc[1])\nshow_image_mask(train_df.iloc[2])","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:41.871061Z","iopub.execute_input":"2022-09-01T08:39:41.871442Z","iopub.status.idle":"2022-09-01T08:39:51.450193Z","shell.execute_reply.started":"2022-09-01T08:39:41.871409Z","shell.execute_reply":"2022-09-01T08:39:51.448870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image enhancement","metadata":{}},{"cell_type":"code","source":"show_image_enhancement(train_df.iloc[1])\nshow_image_enhancement(train_df.iloc[2])","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:51.451936Z","iopub.execute_input":"2022-09-01T08:39:51.452658Z","iopub.status.idle":"2022-09-01T08:39:57.208672Z","shell.execute_reply.started":"2022-09-01T08:39:51.452611Z","shell.execute_reply":"2022-09-01T08:39:57.207171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Analysis Inter/Intra-Class Variance","metadata":{}},{"cell_type":"code","source":"for organ_name in train_df[\"organ\"].unique():\n    filtered_df = train_df.query(\"organ == '%s'\" % organ_name)\n    \n    \n    fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(11, 8))\n    st = plt.suptitle(organ_name.capitalize(), fontsize=16)\n    \n    for i in range(3):\n        image_row = filtered_df.iloc[i]\n        \n        image = read_image(image_row[\"image_path\"], enhancement=True)\n        mask = read_mask(image_row[\"rle\"],\n                         image_shape=(image_row[\"img_width\"], image_row[\"img_height\"]))\n        \n        \n        # Show enhanced Image\n        ax = axs[0][i]\n        ax.set_title(get_image_title(image_row))\n        ax.set_axis_off()\n        \n        ax.imshow(image)\n        \n        # Show Image + Mask\n        ax = axs[1][i]\n        \n        ax.imshow(image)\n        ax.imshow(mask, cmap='seismic',alpha=0.4)\n        ax.set_axis_off()\n        \n    plt.tight_layout() \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:39:57.210892Z","iopub.execute_input":"2022-09-01T08:39:57.211882Z","iopub.status.idle":"2022-09-01T08:40:52.286379Z","shell.execute_reply.started":"2022-09-01T08:39:57.211838Z","shell.execute_reply":"2022-09-01T08:40:52.285115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Compute mean and standard deviations for training set\nREF : https://www.kaggle.com/code/yassinealouini/mean-and-std-statistics-101/notebook","metadata":{}},{"cell_type":"code","source":"max_pixel_value = 255\n\ncount = 0\nsums = []\nfor index, image_row in tqdm(train_df.iterrows()):\n    image = read_image(image_row[\"image_path\"], enhancement=True)\n    \n    count += image.shape[0] * image.shape[1]\n    \n    array_img = np.array(image)\n    normalized_array_img = array_img / max_pixel_value\n    current_sum = normalized_array_img.sum(axis=(0, 1))\n    \n    sums.append(current_sum)\n        \ncomputed_mean = np.array(sums).sum(axis=0) / count  \nprint(\"Mean = %s\" % computed_mean)","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:40:52.287987Z","iopub.execute_input":"2022-09-01T08:40:52.288374Z","iopub.status.idle":"2022-09-01T08:45:30.638775Z","shell.execute_reply.started":"2022-09-01T08:40:52.288339Z","shell.execute_reply":"2022-09-01T08:45:30.637300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Compute STD\nsquared_centered_sums = []\n\nfor index, image_row in tqdm(train_df.iterrows()):\n    image = read_image(image_row[\"image_path\"], enhancement=True)\n    \n    squared_centered_current_sum = (((np.array(image) / max_pixel_value) - computed_mean) ** 2).sum(axis=(0, 1))  \n    squared_centered_sums.append(squared_centered_current_sum)\n    \ncomputed_std = (np.array(squared_centered_sums).sum(axis=0) / count) ** 0.5\nprint(\"STD = %s\" % computed_std)","metadata":{"execution":{"iopub.status.busy":"2022-09-01T08:45:30.643796Z","iopub.execute_input":"2022-09-01T08:45:30.644252Z"},"trusted":true},"execution_count":null,"outputs":[]}]}