{"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 solt==0.1.9","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:22.792428Z","iopub.execute_input":"2023-04-04T06:57:22.792815Z","iopub.status.idle":"2023-04-04T06:57:38.715826Z","shell.execute_reply.started":"2023-04-04T06:57:22.792732Z","shell.execute_reply":"2023-04-04T06:57:38.714393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\nimport pathlib\n\nimport pydicom\nfrom pydicom.errors import InvalidDicomError\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\n\nimport solt\nimport solt.transforms as slt","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:38.718899Z","iopub.execute_input":"2023-04-04T06:57:38.719371Z","iopub.status.idle":"2023-04-04T06:57:41.547957Z","shell.execute_reply.started":"2023-04-04T06:57:38.719319Z","shell.execute_reply":"2023-04-04T06:57:41.546772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcm_loc = pathlib.Path('/kaggle/input/rsna-breast-cancer-detection/train_images/')","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:41.549666Z","iopub.execute_input":"2023-04-04T06:57:41.550542Z","iopub.status.idle":"2023-04-04T06:57:41.556682Z","shell.execute_reply.started":"2023-04-04T06:57:41.550486Z","shell.execute_reply":"2023-04-04T06:57:41.555744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"patient_id = 10006  # folder name, corresponds to patient_id","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:41.559489Z","iopub.execute_input":"2023-04-04T06:57:41.560212Z","iopub.status.idle":"2023-04-04T06:57:41.573194Z","shell.execute_reply.started":"2023-04-04T06:57:41.560174Z","shell.execute_reply":"2023-04-04T06:57:41.571702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filelist = list(dcm_loc.glob(f'{patient_id}/*.dcm'))\nfilelist","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:41.574829Z","iopub.execute_input":"2023-04-04T06:57:41.575199Z","iopub.status.idle":"2023-04-04T06:57:41.598131Z","shell.execute_reply.started":"2023-04-04T06:57:41.575165Z","shell.execute_reply":"2023-04-04T06:57:41.596986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_meta = pd.read_csv(\"/kaggle/input/rsna-breast-cancer-detection/train.csv\")\ntrain_meta.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:41.599817Z","iopub.execute_input":"2023-04-04T06:57:41.600141Z","iopub.status.idle":"2023-04-04T06:57:41.743424Z","shell.execute_reply.started":"2023-04-04T06:57:41.600112Z","shell.execute_reply":"2023-04-04T06:57:41.742288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_meta.describe()","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:59:10.034804Z","iopub.execute_input":"2023-04-04T06:59:10.03535Z","iopub.status.idle":"2023-04-04T06:59:10.110753Z","shell.execute_reply.started":"2023-04-04T06:59:10.035299Z","shell.execute_reply":"2023-04-04T06:59:10.109366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_meta.info()","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:59:17.901962Z","iopub.execute_input":"2023-04-04T06:59:17.902387Z","iopub.status.idle":"2023-04-04T06:59:17.928857Z","shell.execute_reply.started":"2023-04-04T06:59:17.902354Z","shell.execute_reply":"2023-04-04T06:59:17.927897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_meta.tail()","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:59:25.841616Z","iopub.execute_input":"2023-04-04T06:59:25.842153Z","iopub.status.idle":"2023-04-04T06:59:25.867057Z","shell.execute_reply.started":"2023-04-04T06:59:25.842105Z","shell.execute_reply":"2023-04-04T06:59:25.865797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_meta.hist","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:59:33.298347Z","iopub.execute_input":"2023-04-04T06:59:33.298798Z","iopub.status.idle":"2023-04-04T06:59:33.315816Z","shell.execute_reply.started":"2023-04-04T06:59:33.298753Z","shell.execute_reply":"2023-04-04T06:59:33.314966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_dict = {}\nfor i, file in enumerate(filelist):\n    try:\n        ds = pydicom.dcmread(str(file))\n    except InvalidDicomError:\n        print(f'Invalid DICOM file: {str(file)}')\n        continue\n    \n    # print(ds)\n    \n    if hasattr(ds, 'SOPClassUID') and not ds.SOPClassUID == '1.2.840.10008.5.1.4.1.1.1.2':\n        print(f'File has unknown SOPClassUID: {ds.SOPClassUID}')\n        continue\n    \n    if hasattr(ds, 'PresentationIntentType') and not ds.PresentationIntentType == 'FOR PROCESSING':\n        print(f'Invalid Presentation Intent Type: {ds.PresentationIntentType}')\n        continue\n\n    try:\n        arr = ds.pixel_array.copy()  # get pixel array\n    except AttributeError:\n        print(f'AttributeError: Unable to return pixel array.')\n        continue\n    except ValueError:\n        print(f'ValueError: Unable to return pixel array.')\n        continue\n\n    try:\n        out = apply_voi_lut(arr, ds)  # apply VOI LUT (default LUT) or windowing operation\n    except AttributeError:\n        print(f'AttributeError: Unable to apply VOI LUT or windowing.')\n        continue\n    \n    if hasattr(ds, 'PhotometricInterpretation') and not (ds.PhotometricInterpretation == 'MONOCHROME1' or ds.PhotometricInterpretation == 'MONOCHROME2'):\n        print(f'Unknown photometric interpretation: {ds.PhotometricInterpretation}')\n        continue\n    elif not hasattr(ds, 'PhotometricInterpretation'):\n        print(f'Missing photometric interpretation.')\n        continue\n\n    if ds.PhotometricInterpretation == 'MONOCHROME1':  # ranges from bright to dark with ascending pixel values\n        out = out.max() - out\n    elif ds.PhotometricInterpretation == 'MONOCHROME2':  # ranges from dark to bright with ascending pixel values\n        pass\n\n    height = ds.Rows\n    width = ds.Columns\n    \n    out = out.reshape((height, width))  # (height, width)\n\n    if hasattr(ds, 'ImageLaterality'):\n        laterality = ds.ImageLaterality\n    else:\n        print(f'Unknown or invalid Laterality.')\n        continue\n    \n    patient = ds.PatientID\n    \n    try:\n        view = train_meta.loc[( train_meta['patient_id'] == int(patient) ) & ( train_meta['image_id'] == int(file.stem) ), 'view'].item()\n    except ValueError:\n        print(f'ValueError: Unable to return View.')\n        continue\n\n    bitdepth = ds.BitsAllocated\n    # bitsstored = ds.BitsStored\n\n    out = out.astype(np.float64)\n    out /= out.max()\n    out *= pow(2, bitdepth) - 1\n    out = out.astype(np.uint16)\n\n    if laterality == 'R' and view == 'MLO':\n        image_dict['R-MLO'] = out\n    elif laterality == 'L' and view == 'MLO':\n        image_dict['L-MLO'] = out\n    elif laterality == 'R' and view == 'CC':\n        image_dict['R-CC'] = out\n    elif laterality == 'L' and view == 'CC':\n        image_dict['L-CC'] = out\n    \n    # study = ds.StudyInstanceUID","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:41.745334Z","iopub.execute_input":"2023-04-04T06:57:41.745679Z","iopub.status.idle":"2023-04-04T06:57:50.813716Z","shell.execute_reply.started":"2023-04-04T06:57:41.745647Z","shell.execute_reply":"2023-04-04T06:57:50.812476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_dict","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:50.815338Z","iopub.execute_input":"2023-04-04T06:57:50.81586Z","iopub.status.idle":"2023-04-04T06:57:50.825435Z","shell.execute_reply.started":"2023-04-04T06:57:50.815826Z","shell.execute_reply":"2023-04-04T06:57:50.824073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for standard_view in ['R-MLO', 'L-MLO', 'R-CC', 'L-CC']:\n    img = image_dict[standard_view]\n    fig = plt.figure(figsize=(7, 7))\n    ax = fig.add_subplot(1,1,1)\n    ax.imshow(img, cmap='gray')\n    plt.show()\n    \n    unique_colors = len(np.unique(img))\n    mi = np.min(img)\n    ma = np.max(img)\n    print(f'Unique colors: {unique_colors}; Min value: {mi}; Max value: {ma}')\n    \n    del img","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:57:50.827161Z","iopub.execute_input":"2023-04-04T06:57:50.828147Z","iopub.status.idle":"2023-04-04T06:58:01.764716Z","shell.execute_reply.started":"2023-04-04T06:57:50.82811Z","shell.execute_reply":"2023-04-04T06:58:01.76337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dc = solt.DataContainer((image_dict['R-MLO'], ), 'I', transform_settings={0: {'interpolation': 'bilinear'}})  # I stands for \"image\"","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:58:01.769329Z","iopub.execute_input":"2023-04-04T06:58:01.769777Z","iopub.status.idle":"2023-04-04T06:58:01.7778Z","shell.execute_reply.started":"2023-04-04T06:58:01.769741Z","shell.execute_reply":"2023-04-04T06:58:01.776767Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_size = image_dict['R-MLO'].shape[:2]\n\nprob = 0.5\n\nrotation_range_neg = -5\nrotation_range_pos = 5\n\nscale_range_lower = 0.7\nscale_range_upper = 1.3\n\nshear_range_lower = -0.5\nshear_range_upper = 0.5\n\ntranslation_range=50\n\nv_range_min = 0.0000001\nv_range_max=0.00009\n\nuse_cutout = np.random.choice([False, True], p=[1-prob, prob])  # p=[1-p1, p1]\ncutout_proportion = 0.2\ncutout_size = (int(cutout_proportion * image_size[0]), int(cutout_proportion * image_size[1]))\ncutout = slt.CutOut(cutout_size=cutout_size, p=prob)\n\nstream = solt.Stream([\n    slt.Resize(resize_to=image_size),  # here the image is already this fixed size\n    slt.Projection(affine_transforms=solt.Stream([\n        slt.Rotate(angle_range=(rotation_range_neg, rotation_range_pos), p=prob),\n        slt.Scale(range_x=(scale_range_lower, scale_range_upper),\n                  range_y=(scale_range_lower, scale_range_upper),\n                  same=False,\n                  p=prob),\n        slt.Shear(range_x=(shear_range_lower, shear_range_upper),\n                  range_y=(shear_range_lower, shear_range_upper),\n                  interpolation='bilinear',\n                  padding='z',\n                  p=prob),\n        slt.Translate(range_x=translation_range,\n                      range_y=translation_range,\n                      p=prob),\n    ]), v_range=(v_range_min, v_range_max)),\n    # Spatial\n    slt.Pad(pad_to=image_size),\n    slt.Crop(crop_mode='r', crop_to=image_size),\n    slt.Flip(p=prob, axis=1),\n    # Cutout\n    solt.SelectiveStream([\n        cutout if use_cutout else solt.Stream(),\n    ]),\n], ignore_fast_mode=False)","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:58:01.779745Z","iopub.execute_input":"2023-04-04T06:58:01.780493Z","iopub.status.idle":"2023-04-04T06:58:01.92644Z","shell.execute_reply.started":"2023-04-04T06:58:01.780445Z","shell.execute_reply":"2023-04-04T06:58:01.925209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(stream.to_yaml())","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:58:01.92811Z","iopub.execute_input":"2023-04-04T06:58:01.92885Z","iopub.status.idle":"2023-04-04T06:58:01.953661Z","shell.execute_reply.started":"2023-04-04T06:58:01.928813Z","shell.execute_reply":"2023-04-04T06:58:01.952123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(10):\n    res = stream(dc, return_torch=False)  # False is set as we don't want to subtract the ImageNet mean here\n    assert isinstance(res, solt.DataContainer)\n\n    img_res = res.data[0]\n    img = img_res.squeeze()\n    \n    fig = plt.figure(figsize=(5, 5))\n    ax = fig.add_subplot(1,1,1)\n    ax.imshow(img, cmap='gray')\n    plt.show()\n    \n    unique_colors = len(np.unique(img))\n    mi = np.min(img)\n    ma = np.max(img)\n    print(f'Unique colors: {unique_colors}; Min value: {mi}; Max value: {ma}')\n    \n    del img\n    del res\n    del img_res","metadata":{"execution":{"iopub.status.busy":"2023-04-04T06:58:01.954721Z","iopub.execute_input":"2023-04-04T06:58:01.955016Z","iopub.status.idle":"2023-04-04T06:58:25.630902Z","shell.execute_reply.started":"2023-04-04T06:58:01.954987Z","shell.execute_reply":"2023-04-04T06:58:25.629766Z"},"trusted":true},"execution_count":null,"outputs":[]}]}