{"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 python-gdcm","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:46:59.542477Z","iopub.execute_input":"2021-06-28T22:46:59.542938Z","iopub.status.idle":"2021-06-28T22:47:09.989376Z","shell.execute_reply.started":"2021-06-28T22:46:59.542854Z","shell.execute_reply":"2021-06-28T22:47:09.988480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Update","metadata":{}},{"cell_type":"code","source":"import pydicom\nimport numpy as np\nimport json\nimport pandas as pd\n\nfrom fastai.data.all import get_files\nfrom functools import partial\nfrom pathlib import Path\nfrom random import choice\nfrom matplotlib import pyplot as plt\nfrom matplotlib.patches import Rectangle\nfrom IPython.core.pylabtools import print_figure\nfrom collections import Counter\nfrom glob import glob\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom IPython.core.debugger import set_trace\n","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:09.991866Z","iopub.execute_input":"2021-06-28T22:47:09.992315Z","iopub.status.idle":"2021-06-28T22:47:12.789764Z","shell.execute_reply.started":"2021-06-28T22:47:09.992264Z","shell.execute_reply":"2021-06-28T22:47:12.788673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_url = Path(\"../input/siim-covid19-detection\")\n# data_url = Path(\"../data\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.791445Z","iopub.execute_input":"2021-06-28T22:47:12.791756Z","iopub.status.idle":"2021-06-28T22:47:12.796158Z","shell.execute_reply.started":"2021-06-28T22:47:12.791725Z","shell.execute_reply":"2021-06-28T22:47:12.794991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfi = pd.read_csv(data_url/\"train_image_level.csv\")\ndfi.id = dfi.id.apply(lambda x: x.split(\"_\")[0])\ndfi.set_index(\"id\", inplace=True)","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.797713Z","iopub.execute_input":"2021-06-28T22:47:12.798095Z","iopub.status.idle":"2021-06-28T22:47:12.873409Z","shell.execute_reply.started":"2021-06-28T22:47:12.798059Z","shell.execute_reply":"2021-06-28T22:47:12.872234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"get_dicoms = partial(get_files, extensions=['.dcm'])","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.874673Z","iopub.execute_input":"2021-06-28T22:47:12.874999Z","iopub.status.idle":"2021-06-28T22:47:12.879109Z","shell.execute_reply.started":"2021-06-28T22:47:12.874967Z","shell.execute_reply":"2021-06-28T22:47:12.878172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfs = pd.read_csv(data_url/'train_study_level.csv')\ndfs.id = dfs.id.apply(lambda x: x.split(\"_\")[0])\ndfs.set_index('id', inplace=True)","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.880482Z","iopub.execute_input":"2021-06-28T22:47:12.880785Z","iopub.status.idle":"2021-06-28T22:47:12.913275Z","shell.execute_reply.started":"2021-06-28T22:47:12.880755Z","shell.execute_reply":"2021-06-28T22:47:12.912302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Study:\n    _cats = [ \"Negative for Pneumonia\", \"Typical Appearance\", \"Indeterminate Appearance\", \"Atypical Appearance\"]\n    def __init__(self, path):\n        if isinstance(path, Path):\n            self.path = path\n        else:\n            self.path = list((data_url/\"train\").glob(path))[0]\n        self.dcms = [DCM(_) for _ in get_dicoms(self.path)]\n    def __len__(self): return len(self.dcms)\n\n    @property\n    def result(self): return self._cats[np.argmax(dfs.loc[self.path.stem])]\n    \n    @property\n    def _figure(self):\n        cols=4\n        rows=len(self)//5+1\n        fig, axs = plt.subplots(rows, cols, figsize=(14, rows*3.5+1), \n                                gridspec_kw={'hspace':0.5, 'wspace':0.0},\n                                squeeze=False)\n        axs=axs.ravel()\n        for i, dcm in enumerate(self.dcms): self.dcms[i].plot(axs[i])\n        for ax in axs[len(self):]:ax.axis('off')\n\n        data = print_figure(fig)\n        fig.suptitle(f\"{self.__class__.__name__}: {self.path.stem} {self.result}\")\n        plt.close(fig)\n        return fig\n\n    def _repr_png_(self):\n        data = print_figure(self._figure)\n        return data","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.915902Z","iopub.execute_input":"2021-06-28T22:47:12.916220Z","iopub.status.idle":"2021-06-28T22:47:12.927735Z","shell.execute_reply.started":"2021-06-28T22:47:12.916187Z","shell.execute_reply":"2021-06-28T22:47:12.926544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DCM:\n    def __init__(self, path):\n        if isinstance(path, Path):\n            self.path = path\n        else:\n            self.path = list((data_url/\"train\").glob(f\"**/{path}.dcm\"))[0]\n        self._dcm = None\n    @property\n    def label(self): return dfi.loc[self.name].label\n\n    @property\n    def dcm(self):\n        if self._dcm is None:\n            dicom = pydicom.read_file(self.path)\n            try:\n                data = apply_voi_lut(dicom.pixel_array, dicom)\n            except RuntimeError:\n                data = dicom.pixel_array\n            if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n                data = np.amax(data) - data\n        \n            data = data - np.min(data)\n            data = data / np.max(data)\n            self._dcm = (data * 255).astype(np.uint8)\n            \n            try: self.patient_sex = dicom.PatientSex\n            except AttributeError: self.patient_sex = \"NA\"\n            try: self.body_part_examined = dicom.BodyPartExamined\n            except AttributeError: self.body_part_examined = \"NA\"\n            \n        return self._dcm\n    \n    @property\n    def boxes(self):\n        try: return json.loads(dfi.loc[self.name].boxes.replace(\"'\", \"\\\"\"))\n        except AttributeError: return []\n    \n    def plot(self, ax):\n        ax.imshow(self.dcm, cmap='gray')\n        ax.set_xticks([])\n        ax.set_yticks([])\n        ax.set_title(f'{self.name}\\nBody Part:{self.body_part_examined}\\nPatient Sex:{self.patient_sex}')\n\n        for box in self.boxes:\n            x, y, w, h = box.values()\n            ax.add_patch(Rectangle((x, y), w, h, edgecolor=\"red\", fill=False))\n        \n    @property\n    def name(self): return self.path.stem\n    def _repr_png_(self):\n        fig, ax = plt.subplots()\n        self.plot(ax)\n        plt.close(fig)\n        data = print_figure(fig)\n        return data\n    \n    def __len__(self): return 1","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.929647Z","iopub.execute_input":"2021-06-28T22:47:12.930080Z","iopub.status.idle":"2021-06-28T22:47:12.946775Z","shell.execute_reply.started":"2021-06-28T22:47:12.930044Z","shell.execute_reply":"2021-06-28T22:47:12.945617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## data structure\n# study/series/image","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.948543Z","iopub.execute_input":"2021-06-28T22:47:12.949129Z","iopub.status.idle":"2021-06-28T22:47:12.962821Z","shell.execute_reply.started":"2021-06-28T22:47:12.949083Z","shell.execute_reply":"2021-06-28T22:47:12.961753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"get_dicoms = partial(get_files, extensions=['.dcm'])\ndcms = get_dicoms(path=data_url/\"train\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:12.965203Z","iopub.execute_input":"2021-06-28T22:47:12.965577Z","iopub.status.idle":"2021-06-28T22:47:34.153041Z","shell.execute_reply.started":"2021-06-28T22:47:12.965516Z","shell.execute_reply":"2021-06-28T22:47:34.152254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DCM(\"1018aa051dd9\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:34.154084Z","iopub.execute_input":"2021-06-28T22:47:34.154482Z","iopub.status.idle":"2021-06-28T22:47:45.338934Z","shell.execute_reply.started":"2021-06-28T22:47:34.154452Z","shell.execute_reply":"2021-06-28T22:47:45.337773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"PatientSex\nBodyPartExamined","metadata":{}},{"cell_type":"code","source":"study_counter = Counter([_.parent.parent for _ in dcms])\nstudys = [Study(_) for _ in list(study_counter.elements())]\n# for p, i in studys.most_common(50): Study(p)","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:45.340262Z","iopub.execute_input":"2021-06-28T22:47:45.340588Z","iopub.status.idle":"2021-06-28T22:47:50.924982Z","shell.execute_reply.started":"2021-06-28T22:47:45.340556Z","shell.execute_reply":"2021-06-28T22:47:50.923872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"choice(studys)","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:50.926509Z","iopub.execute_input":"2021-06-28T22:47:50.927008Z","iopub.status.idle":"2021-06-28T22:47:53.597096Z","shell.execute_reply.started":"2021-06-28T22:47:50.926962Z","shell.execute_reply":"2021-06-28T22:47:53.595886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DCM(choice(dcms))","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:53.598415Z","iopub.execute_input":"2021-06-28T22:47:53.598718Z","iopub.status.idle":"2021-06-28T22:47:54.979509Z","shell.execute_reply.started":"2021-06-28T22:47:53.598681Z","shell.execute_reply":"2021-06-28T22:47:54.978476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"7e91e041c7d4\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:47:54.981031Z","iopub.execute_input":"2021-06-28T22:47:54.981342Z","iopub.status.idle":"2021-06-28T22:48:03.612470Z","shell.execute_reply.started":"2021-06-28T22:47:54.981312Z","shell.execute_reply":"2021-06-28T22:48:03.611447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DCM(\"d3885c0f58bb\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:03.613961Z","iopub.execute_input":"2021-06-28T22:48:03.614556Z","iopub.status.idle":"2021-06-28T22:48:14.772634Z","shell.execute_reply.started":"2021-06-28T22:48:03.614511Z","shell.execute_reply":"2021-06-28T22:48:14.771896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"a7335b2f9815\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:14.773628Z","iopub.execute_input":"2021-06-28T22:48:14.773995Z","iopub.status.idle":"2021-06-28T22:48:28.271825Z","shell.execute_reply.started":"2021-06-28T22:48:14.773967Z","shell.execute_reply":"2021-06-28T22:48:28.270532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"8943d1d85097\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:28.273539Z","iopub.execute_input":"2021-06-28T22:48:28.273927Z","iopub.status.idle":"2021-06-28T22:48:35.157371Z","shell.execute_reply.started":"2021-06-28T22:48:28.273889Z","shell.execute_reply":"2021-06-28T22:48:35.156382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"970c96c9fa5d\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:35.158785Z","iopub.execute_input":"2021-06-28T22:48:35.159350Z","iopub.status.idle":"2021-06-28T22:48:45.090972Z","shell.execute_reply.started":"2021-06-28T22:48:35.159294Z","shell.execute_reply":"2021-06-28T22:48:45.090180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"7e91e041c7d4\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:45.092035Z","iopub.execute_input":"2021-06-28T22:48:45.092450Z","iopub.status.idle":"2021-06-28T22:48:52.820170Z","shell.execute_reply.started":"2021-06-28T22:48:45.092419Z","shell.execute_reply":"2021-06-28T22:48:52.819363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"4c45ac349e3a\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:52.821199Z","iopub.execute_input":"2021-06-28T22:48:52.821614Z","iopub.status.idle":"2021-06-28T22:48:57.167260Z","shell.execute_reply.started":"2021-06-28T22:48:52.821581Z","shell.execute_reply":"2021-06-28T22:48:57.166067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"26648048b098\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:48:57.170254Z","iopub.execute_input":"2021-06-28T22:48:57.170613Z","iopub.status.idle":"2021-06-28T22:49:03.177121Z","shell.execute_reply.started":"2021-06-28T22:48:57.170569Z","shell.execute_reply":"2021-06-28T22:49:03.176024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"1e96d5eb4c91\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:49:03.178874Z","iopub.execute_input":"2021-06-28T22:49:03.179285Z","iopub.status.idle":"2021-06-28T22:49:06.886877Z","shell.execute_reply.started":"2021-06-28T22:49:03.179240Z","shell.execute_reply":"2021-06-28T22:49:06.885869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"1de3b9724942\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:49:06.888273Z","iopub.execute_input":"2021-06-28T22:49:06.888690Z","iopub.status.idle":"2021-06-28T22:49:10.779659Z","shell.execute_reply.started":"2021-06-28T22:49:06.888656Z","shell.execute_reply":"2021-06-28T22:49:10.778755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"72044bb44d41\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:49:10.780835Z","iopub.execute_input":"2021-06-28T22:49:10.781125Z","iopub.status.idle":"2021-06-28T22:49:13.444863Z","shell.execute_reply.started":"2021-06-28T22:49:10.781094Z","shell.execute_reply":"2021-06-28T22:49:13.443811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Study(\"7e91e041c7d4\")","metadata":{"execution":{"iopub.status.busy":"2021-06-28T22:49:13.446126Z","iopub.execute_input":"2021-06-28T22:49:13.446455Z","iopub.status.idle":"2021-06-28T22:49:21.296259Z","shell.execute_reply.started":"2021-06-28T22:49:13.446422Z","shell.execute_reply":"2021-06-28T22:49:21.295269Z"},"trusted":true},"execution_count":null,"outputs":[]}]}