{"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":"%matplotlib inline\n#這是juoyter notebook的magic word˙\n\nimport matplotlib\nimport matplotlib.pyplot as plt\nfrom IPython import display","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-07-24T16:47:46.897095Z","iopub.execute_input":"2021-07-24T16:47:46.897753Z","iopub.status.idle":"2021-07-24T16:47:46.910221Z","shell.execute_reply.started":"2021-07-24T16:47:46.897664Z","shell.execute_reply":"2021-07-24T16:47:46.909319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n#判斷是否在jupyter notebook上\ndef is_in_ipython():\n    \"Is the code running in the ipython environment (jupyter including)\"\n    program_name = os.path.basename(os.getenv('_', ''))\n\n    if ('jupyter-notebook' in program_name or # jupyter-notebook\n        'ipython'          in program_name or # ipython\n        'jupyter' in program_name or  # jupyter\n        'JPY_PARENT_PID'   in os.environ):    # ipython-notebook\n        return True\n    else:\n        return False\n\n\n#判斷是否在colab上\ndef is_in_colab():\n    if not is_in_ipython(): return False\n    try:\n        from google import colab\n        return True\n    except: return False\n\n#判斷是否在kaggke_kernal上\ndef is_in_kaggle_kernal():\n    if 'kaggle' in os.environ['PYTHONPATH']:\n        return True\n    else:\n        return False\n\nif is_in_colab():\n    from google.colab import drive\n    drive.mount('/content/gdrive')","metadata":{"execution":{"iopub.status.busy":"2021-07-24T16:47:46.958438Z","iopub.execute_input":"2021-07-24T16:47:46.959033Z","iopub.status.idle":"2021-07-24T16:47:46.965800Z","shell.execute_reply.started":"2021-07-24T16:47:46.959000Z","shell.execute_reply":"2021-07-24T16:47:46.964820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ['TRIDENT_BACKEND'] = 'pytorch'\n\nif is_in_kaggle_kernal():\n    os.environ['TRIDENT_HOME'] = './trident'\n    \nelif is_in_colab():\n    os.environ['TRIDENT_HOME'] = '/content/gdrive/My Drive/trident'\n\n#為確保安裝最新版 \n!pip uninstall tridentx -y\n!pip install tridentx --upgrade\n!pip install pydicom --upgrade\n!pip install python-gdcm  --upgrade\n!pip install imutils\nimport imutils\nimport json\nimport copy\nimport numpy as np\n#調用trident api\nimport trident as T\nfrom trident import *\nfrom trident.models import resnet,efficientnet\nimport random\nfrom tqdm import tqdm\nimport pydicom\nimport gdcm\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport scipy","metadata":{"execution":{"iopub.status.busy":"2021-07-24T16:48:02.456760Z","iopub.execute_input":"2021-07-24T16:48:02.457092Z","iopub.status.idle":"2021-07-24T16:48:37.814428Z","shell.execute_reply.started":"2021-07-24T16:48:02.457063Z","shell.execute_reply":"2021-07-24T16:48:37.813688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_images=glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/*/*/*.dcm')\n\nprint(len(dicom_images))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"flairs=glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/FLAIR/*.dcm')\nt1ws=glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/T1w/*.dcm')\nt1wces=glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/T1wCE/*.dcm')\nt2ws=glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/T2w/*.dcm')\nprint( pydicom.read_file(flairs[0]))\nprint(pydicom.read_file(flairs[0])[0x0020, 0x0032])\nprint(pydicom.read_file(flairs[0])[0x0020, 0x0037])\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"t1ws=glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00009/T1w/*.dcm')\n\nprint(len(t1ws))\nprint( pydicom.read_file(t1ws[0]))\nprint( pydicom.read_file(t1ws[16]).pixel_array)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_scan(path):\n    \"\"\"\n    回傳資料夾中所有的slices\n    :param path:\n    :return:\n    \"\"\"\n    g = glob.glob(path + '/*.dcm')\n    slices = [pydicom.read_file(s) for s in g]\n    slices.sort(key=lambda x: int(x.InstanceNumber))\n    return slices\n\ndef get_pixels(slices):\n    #讀出像素值並且儲存成numpy的格式\n    image = np.stack([s.pixel_array for s in slices])\n    check_max=np.array([im.max() for im in image])\n    check_max[check_max>0]=1\n    if check_max.sum()==0:\n        print('check_max.sum()==0')\n        return np.zeros((100,100,100)),None\n        \n    start=np.argmax(check_max)-1\n    end=len(check_max)-(np.argmax(check_max[::-1])-1)\n    if end<start:\n        end=start\n    \n    filtered_slices=slices[start:end+1]\n    if len(filtered_slices)<=2:\n        return np.zeros((100,100,100)),None\n    \n    image=image[start:end+1]\n    # 將超過機器掃描範圍的部分設為 0\n    # 通常intercept是 -1024, 經過計算之後空氣大約是 0\n    image[image < 0] = 0\n    intercept = filtered_slices[0].RescaleIntercept\n    slope = filtered_slices[0].RescaleSlope\n    # 轉換為Hounsfield units (HU)\n    if slope != 1:\n        for slice_number in range(len(filtered_slices)):\n\n            image[slice_number] = slope * image[slice_number].astype(np.float64)\n            image[slice_number] = image[slice_number].astype(np.int16)\n\n            image[slice_number] += np.int16(intercept)\n    \n    return np.array(image, dtype=np.int16),filtered_slices\n\ndef resample(image, scan, new_spacing=[1.0, 1.0, 1.0]):\n    if scan is None or (image.shape==(100,100,100) and image.sum()==0):\n        return  np.zeros((100,100,100))\n    #取出原本的spacing\n    #[scan[0].SliceThickness] + list(scan[0].PixelSpacing) 會組成一個list，裡面是的spacing數值\n    spacing = np.array([scan[0].SliceThickness] + list(scan[0].PixelSpacing), dtype=np.float64)\n    \n    if not hasattr(scan[0],'SliceLocation'):\n        scan[0].SliceLocation=-1*slices[0][('0020','0032')].value[1]\n        print('loc_start',-1*slices[0][('0020','0032')].value[1])\n    if not hasattr(scan[-1],'SliceLocation'):\n        scan[-1].SliceLocation=-1*slices[-1][('0020','0032')].value[1]\n        print('loc_end',-1*slices[-1][('0020','0032')].value[1])\n\n        \n    if scan[-1].SliceLocation<scan[0].SliceLocation :\n        scan=scan[::-1]\n    loc_start=scan[0].SliceLocation \n    loc_end=scan[-1].SliceLocation+scan[-1].SliceThickness\n    \n    resize_factor = spacing / new_spacing\n    new_real_shape = image.shape  * resize_factor\n    \n    new_shape = np.round(new_real_shape)\n    \n    real_resize_factor = new_shape /image.shape\n    \n    real_resize_factor[0]=float(builtins.min(loc_end-loc_start,256))/(image.shape[0])\n    #print('real_resize_factor',real_resize_factor)\n    new_spacing = spacing / real_resize_factor\n    \n    #計算出放大參數後，用scipy對維照片進行縮放，scipy會自動為圖片進行插補\n    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode='nearest')\n    image[image<0]=0\n    return image\n\n\ndef crop_brain(image,normalized=True):\n    if image is None or image.shape==(100,100,100) or image.sum()==0:\n        return image\n    \n    flatten_image=image.max(0)\n    rows=flatten_image.max(1)\n    rows[rows > 0] = 1\n    columns=flatten_image.max(0)\n    columns[columns > 0] = 1\n    y_start=np.argmax(rows)-1\n    y_end=len(rows)-(np.argmax(rows[::-1])-1)\n    x_start=np.argmax(columns)-1\n    x_end=len(columns)-(np.argmax(columns[::-1])-1)\n    crop_image=image[:,y_start:y_end+1,x_start:x_end+1]\n#     if normalized:\n#         mask=crop_image>0\n#         hist,bins = np.histogram((crop_image[mask]).reshape(-1),bins =100)\n#         base_value=bins[np.argmax(hist)]\n#         crop_image=np.clip((crop_image-base_value)/base_value,-1,1)\n#         crop_image[1-mask]=-1\n    if normalized:\n        mask=crop_image>0\n        if len(crop_image[mask])>0:\n            mean_value=crop_image[mask].mean()\n            std_value=crop_image[mask].std()\n            if std_value>0:\n                crop_image=(crop_image-mean_value)/std_value\n    return crop_image\n\nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\nimport numpy as np\nfrom skimage import measure\n\ndef plot_3d(image, threshold=-300): \n    p = image.transpose(2,1,0)\n    verts, faces, normals, values = measure.marching_cubes_lewiner(p, threshold)\n    fig = plt.figure(figsize=(10, 10))\n    ax = fig.add_subplot(111, projection='3d')\n    mesh = Poly3DCollection(verts[faces], alpha=0.1)\n    face_color = [0.5, 0.5, 1]\n    mesh.set_facecolor(face_color)\n    ax.add_collection3d(mesh)\n    ax.set_xlim(0, p.shape[0])\n    ax.set_ylim(0, p.shape[1])\n    ax.set_zlim(0, p.shape[2])\n    \n\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-24T19:05:28.721995Z","iopub.execute_input":"2021-07-24T19:05:28.722622Z","iopub.status.idle":"2021-07-24T19:05:28.748530Z","shell.execute_reply.started":"2021-07-24T19:05:28.722582Z","shell.execute_reply":"2021-07-24T19:05:28.747474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nslices = load_scan('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00000/FLAIR')\nprint(len(slices))\npatient_pixels,filtered_slices = get_pixels(slices)\n\nprint(patient_pixels.shape)\nprint(patient_pixels.min(),patient_pixels.max())\nimage= resample(patient_pixels, filtered_slices)\n\nprint(image.shape)\nprint(image.min(),image.max())\ncrop_image=crop_brain(image)\n\nprint(crop_image.shape)\nprint(crop_image.min(),crop_image.mean(),crop_image.max())\n","metadata":{"execution":{"iopub.status.busy":"2021-07-24T17:00:12.756984Z","iopub.execute_input":"2021-07-24T17:00:12.757462Z","iopub.status.idle":"2021-07-24T17:00:28.565368Z","shell.execute_reply.started":"2021-07-24T17:00:12.757430Z","shell.execute_reply":"2021-07-24T17:00:28.564311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(slices[0])","metadata":{"execution":{"iopub.status.busy":"2021-07-24T17:02:18.693441Z","iopub.execute_input":"2021-07-24T17:02:18.693835Z","iopub.status.idle":"2021-07-24T17:02:18.701692Z","shell.execute_reply.started":"2021-07-24T17:02:18.693802Z","shell.execute_reply":"2021-07-24T17:02:18.700184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for k in range(len(patient_pixels)):\n    slice=patient_pixels[k]\n    \n    mask=slice>0\n    hist,bins = np.histogram(slice[mask],bins =100 )\n    print(k,'peak',bins[np.argmax(hist)],'max:',slice.max(),'mean:',slice[mask].mean())\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"slices = load_scan('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00095/FLAIR')\nprint(len(slices))\npatient_pixels,filtered_slices= get_pixels(slices)\n\nprint(patient_pixels.shape)\nprint(patient_pixels.min(),patient_pixels.max())\nimage = resample(patient_pixels, filtered_slices)\n\nprint(image.shape)\nprint(image.min(),image.max())\ncrop_image=crop_brain(image,normalized=True)\n\nprint(crop_image.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nplot_3d(image.copy(),threshold=500)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#3d圖不支持ax.set_aspect('equal')，因此比例會看起來怪怪的\ncrop_image=crop_brain(image,normalized=False)\nplot_3d(crop_image.copy(),threshold=500)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"slices = load_scan('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/00095/T2w')\nprint(len(slices))\npatient_pixels,filtered_slices= get_pixels(slices)\nprint(filtered_slices[0])\n\nprint(patient_pixels.shape)\nprint(patient_pixels.min(),patient_pixels.max())\nimage = resample(patient_pixels, filtered_slices)\nimage[image < 0] = 0\nprint(image.shape)\nprint(image.min(),image.max())\ncrop_image=crop_brain(image)\n\nprint(crop_image.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"crop_image=crop_brain(image,normalized=False)\nplot_3d(crop_image.copy(),threshold=400)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"crop_image=crop_brain(image,normalized=False)\nplot_3d(np.flip(np.transpose(crop_image,(1,2,0)).copy(),axis=-1),threshold=400)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"files=glob.glob('../input/rsna-miccai-brain-tumor-baseline/train/*/*.npz')\nprint(len(files))","metadata":{"execution":{"iopub.status.busy":"2021-07-24T08:27:45.803305Z","iopub.execute_input":"2021-07-24T08:27:45.803658Z","iopub.status.idle":"2021-07-24T08:27:46.818131Z","shell.execute_reply.started":"2021-07-24T08:27:45.803605Z","shell.execute_reply":"2021-07-24T08:27:46.816937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nfor file in files:\n    try:\n        new_file=file.replace('../input/rsna-miccai-brain-tumor-baseline/train','./train')\n        make_dir_if_need(new_file)\n        img=np.load(file)['arr_0']\n        _,filename,_=split_path(new_file)\n        print(filename, img.max(),img.min())\n        shutil.copy(file,new_file)\n        \n        \n    except:\n        pass\n\n    ","metadata":{"execution":{"iopub.status.busy":"2021-07-24T08:27:51.332527Z","iopub.execute_input":"2021-07-24T08:27:51.333007Z","iopub.status.idle":"2021-07-24T08:32:49.262477Z","shell.execute_reply.started":"2021-07-24T08:27:51.332967Z","shell.execute_reply":"2021-07-24T08:32:49.261585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nfrom tqdm import tqdm\ndf_train=pd.read_csv('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv')\nprint(df_train)\n\nlabels=[]\ntypes=[]\nimages=[]\nfor i in tqdm(range(len(df_train['BraTS21ID']))):\n    id=df_train['BraTS21ID'][i]\n    img_path1='{0}/{1}_FLAIR.npz'.format(('00000'+str(id))[-5:],('00000'+str(id))[-5:])\n \n    labels.append(df_train['MGMT_value'][i])\n    images.append(img_path1)\n    types.append(0)\n    img_path2='{0}/{1}_T1w.npz'.format(('00000'+str(id))[-5:],('00000'+str(id))[-5:])\n\n    labels.append(2+df_train['MGMT_value'][i])\n    images.append(img_path2)\n    types.append(1)\n    img_path3='{0}/{1}_T1wCE.npz'.format(('00000'+str(id))[-5:],('00000'+str(id))[-5:])\n\n    labels.append(4+df_train['MGMT_value'][i])\n    images.append(img_path3)\n    types.append(2)\n    img_path4='{0}/{1}_T2w.npz'.format(('00000'+str(id))[-5:],('00000'+str(id))[-5:])\n\n    labels.append(6+df_train['MGMT_value'][i])\n    images.append(img_path4)\n    types.append(3)\nprint(len(labels))\nprint(len(images))","metadata":{"execution":{"iopub.status.busy":"2021-07-24T17:01:02.299037Z","iopub.execute_input":"2021-07-24T17:01:02.299572Z","iopub.status.idle":"2021-07-24T17:01:02.363301Z","shell.execute_reply.started":"2021-07-24T17:01:02.299534Z","shell.execute_reply":"2021-07-24T17:01:02.360948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def prepare_image(img_path):\n    start_time=time.time()\n    print('start thread: {0}'.format(img_path),flush=True)\n    try:\n        _,filename,_=split_path(img_path)\n        new_file_path=os.path.join('./train',img_path)\n        make_dir_if_need(new_file_path)\n        patient_id,mri_type=filename.split('_')\n        if not os.path.exists(new_file_path) :\n            \n            if int(patient_id)>0 and int(patient_id)%10==0:\n                gc.collect()\n            start_time1=time.time()\n            slices = load_scan(os.path.join('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train',patient_id,mri_type))\n            print('Get slices: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n            start_time1=time.time()\n            patient_pixels,filtered_slices= get_pixels(slices)\n            print('Get pixels: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n            start_time1=time.time()\n            image = resample(patient_pixels, filtered_slices)\n            print('Resample: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n            start_time1=time.time()\n            img=crop_brain(image)\n            print('Crop image\\: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n\n            with open(new_file_path, 'wb') as f:\n                np.savez_compressed(f, img)\n            print('end thread: {0}  {1}'.format(img_path,time.time() - start_time),flush=True)\n            del slices\n            del filtered_slices\n            del image\n            del patient_pixels\n            del img\n            return True\n        else:\n            #print('end thread exists: {0}  {1}'.format(img_path,time.time() - start_time),flush=True)\n            return True\n    except Exception as e:\n        print(e)\n        img=np.zeros((100,100,100)).astype(np.float32)\n        print('end thread: {0}  {1}'.format(img_path,time.time() - start_time),flush=True)\n        return True","metadata":{"execution":{"iopub.status.busy":"2021-07-24T19:06:00.567930Z","iopub.execute_input":"2021-07-24T19:06:00.568272Z","iopub.status.idle":"2021-07-24T19:06:00.579102Z","shell.execute_reply.started":"2021-07-24T19:06:00.568242Z","shell.execute_reply":"2021-07-24T19:06:00.578119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for img in images:\n    prepare_image(img)","metadata":{"execution":{"iopub.status.busy":"2021-07-24T19:06:05.819831Z","iopub.execute_input":"2021-07-24T19:06:05.820179Z","iopub.status.idle":"2021-07-24T21:44:30.842591Z","shell.execute_reply.started":"2021-07-24T19:06:05.820149Z","shell.execute_reply":"2021-07-24T21:44:30.840820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"from concurrent.futures import ThreadPoolExecutor\n\n\n\ndef prepare_image(img_path):\n    start_time=time.time()\n    print('start thread: {0}'.format(img_path),flush=True)\n    try:\n        _,filename,_=split_path(img_path)\n        new_file_path=os.path.join('./train',img_path)\n        make_dir_if_need(new_file_path)\n        patient_id,mri_type=filename.split('_')\n        if not os.path.exists(new_file_path) or int(patient_id)>=455:\n            \n            if int(patient_id)>0 and int(patient_id)%10==0:\n                gc.collect()\n            start_time1=time.time()\n            slices = load_scan(os.path.join('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train',patient_id,mri_type))\n            print('Get slices: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n            start_time1=time.time()\n            patient_pixels,filtered_slices= get_pixels(slices)\n            print('Get pixels: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n            start_time1=time.time()\n            image = resample(patient_pixels, filtered_slices)\n            print('Resample: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n            start_time1=time.time()\n            img=crop_brain(image)\n            print('Crop image\\: {0}  {1}'.format(img_path,time.time() - start_time1),flush=True)\n\n            with open(new_file_path, 'wb') as f:\n                np.savez_compressed(f, img)\n            print('end thread: {0}  {1}'.format(img_path,time.time() - start_time),flush=True)\n            del slices\n            del filtered_slices\n            del image\n            del patient_pixels\n            del img\n            return True\n        else:\n            #print('end thread exists: {0}  {1}'.format(img_path,time.time() - start_time),flush=True)\n            return True\n    except Exception as e:\n        print(e)\n        img=np.zeros((100,100,100)).astype(np.float32)\n        print('end thread: {0}  {1}'.format(img_path,time.time() - start_time),flush=True)\n        return True\n    \nimport concurrent.futures\nwith concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:\n \n    future_to_folder = {executor.submit(prepare_image, img_path): img_path for img_path in images}\n    for future in concurrent.futures.as_completed(future_to_folder):\n        foler = future_to_folder[future]\n        try:\n            data = future.result()\n            \n        except Exception as exc:\n            print(exc)\n       \n            ","metadata":{"execution":{"iopub.status.busy":"2021-07-23T16:43:32.204352Z","iopub.execute_input":"2021-07-23T16:43:32.204806Z"}}},{"cell_type":"markdown","source":"arr=np.load('./resample_images/00000/00000_flair.npz')['arr_0']\nprint(arr.shape)\nprint(arr.max())","metadata":{"execution":{"iopub.status.busy":"2021-07-18T11:24:00.24356Z","iopub.execute_input":"2021-07-18T11:24:00.243947Z","iopub.status.idle":"2021-07-18T11:24:00.316776Z","shell.execute_reply.started":"2021-07-18T11:24:00.243912Z","shell.execute_reply":"2021-07-18T11:24:00.31576Z"}}},{"cell_type":"markdown","source":"from matplotlib import animation, rc\nrc('animation', html='jshtml')\n\n\ndef create_animation(ims):\n    fig = plt.figure(figsize=(6, 6))\n    plt.axis('off')\n    im = plt.imshow(ims[0]/builtins.max(ims[0].max(),1), cmap=\"gray\")\n\n    def animate_func(i):\n        im.set_array(ims[i]/builtins.max(ims[i].max(),1))\n        return [im]\n\n    return animation.FuncAnimation(fig, animate_func, frames = len(ims), interval = 1000//24)","metadata":{"execution":{"iopub.status.busy":"2021-07-18T11:25:11.285222Z","iopub.execute_input":"2021-07-18T11:25:11.286309Z","iopub.status.idle":"2021-07-18T11:25:11.295238Z","shell.execute_reply.started":"2021-07-18T11:25:11.28626Z","shell.execute_reply":"2021-07-18T11:25:11.293322Z"}}},{"cell_type":"markdown","source":"plt.imshow(arr[100]/arr[100].max(), cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2021-07-18T11:23:08.186822Z","iopub.execute_input":"2021-07-18T11:23:08.187232Z","iopub.status.idle":"2021-07-18T11:23:08.3732Z","shell.execute_reply.started":"2021-07-18T11:23:08.187195Z","shell.execute_reply":"2021-07-18T11:23:08.372466Z"}}},{"cell_type":"markdown","source":"\ncreate_animation(arr)","metadata":{"execution":{"iopub.status.busy":"2021-07-18T11:25:17.241886Z","iopub.execute_input":"2021-07-18T11:25:17.242246Z","iopub.status.idle":"2021-07-18T11:25:25.837838Z","shell.execute_reply.started":"2021-07-18T11:25:17.242214Z","shell.execute_reply":"2021-07-18T11:25:25.837155Z"}}}]}