{"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":"markdown","source":"# about\nI extracted metadata from DICOM files. You can download csv file from my output.\n\n# reference\n- https://www.kaggle.com/c/rsna-miccai-brain-tumor-radiogenomic-classification/discussion/252942","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport pydicom","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-26T03:33:57.967375Z","iopub.execute_input":"2021-08-26T03:33:57.967904Z","iopub.status.idle":"2021-08-26T03:33:58.300363Z","shell.execute_reply.started":"2021-08-26T03:33:57.967871Z","shell.execute_reply":"2021-08-26T03:33:58.299434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%ls ../input/rsna-miccai-brain-tumor-radiogenomic-classification","metadata":{"execution":{"iopub.status.busy":"2021-08-26T03:33:58.302012Z","iopub.execute_input":"2021-08-26T03:33:58.30246Z","iopub.status.idle":"2021-08-26T03:33:59.052822Z","shell.execute_reply.started":"2021-08-26T03:33:58.302416Z","shell.execute_reply":"2021-08-26T03:33:59.0519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pydicom import dcmread\ndata_dir = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification'\nfpath = data_dir + '/train/00000/FLAIR/Image-1.dcm'\nds = dcmread(fpath)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T03:33:59.055048Z","iopub.execute_input":"2021-08-26T03:33:59.055697Z","iopub.status.idle":"2021-08-26T03:33:59.078234Z","shell.execute_reply.started":"2021-08-26T03:33:59.055645Z","shell.execute_reply":"2021-08-26T03:33:59.077146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sample data\nprint(ds)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T03:33:59.080241Z","iopub.execute_input":"2021-08-26T03:33:59.080722Z","iopub.status.idle":"2021-08-26T03:33:59.087815Z","shell.execute_reply.started":"2021-08-26T03:33:59.080687Z","shell.execute_reply":"2021-08-26T03:33:59.087077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dicom metadata\n","metadata":{}},{"cell_type":"code","source":"from tqdm import tqdm\n\nclass Dicom:\n    def __init__(self):\n        self.fields = [\n            'AccessionNumber',\n            'AcquisitionMatrix',\n            'B1rms',\n            'BitsAllocated',\n            'BitsStored',\n            'Columns',\n            'ConversionType',\n            'DiffusionBValue',\n            'DiffusionGradientOrientation',\n            'EchoNumbers',\n            'EchoTime',\n            'EchoTrainLength',\n            'FlipAngle',\n            'HighBit',\n            'HighRRValue',\n            'ImageDimensions',\n            'ImageFormat',\n            'ImageGeometryType',\n            'ImageLocation',\n            'ImageOrientation',\n            'ImageOrientationPatient',\n            'ImagePosition',\n            'ImagePositionPatient',\n            'ImageType',\n            'ImagedNucleus',\n            'ImagingFrequency',\n            'InPlanePhaseEncodingDirection',\n            'InStackPositionNumber',\n            'InstanceNumber',\n            'InversionTime',\n            'Laterality',\n            'LowRRValue',\n            'MRAcquisitionType',\n            'MagneticFieldStrength',\n            'Modality',\n            'NumberOfAverages',\n            'NumberOfPhaseEncodingSteps',\n            'PatientID',\n            'PatientName',\n            'PatientPosition',\n            'PercentPhaseFieldOfView',\n            'PercentSampling',\n            'PhotometricInterpretation',\n            'PixelBandwidth',\n            'PixelPaddingValue',\n            'PixelRepresentation',\n            'PixelSpacing',\n            'PlanarConfiguration',\n            'PositionReferenceIndicator',\n            'PresentationLUTShape',\n            'ReconstructionDiameter',\n            'RescaleIntercept',\n            'RescaleSlope',\n            'RescaleType',\n            'Rows',\n            'SAR',\n            'SOPClassUID',\n            'SOPInstanceUID',\n            'SamplesPerPixel',\n            'SeriesDescription',\n            'SeriesInstanceUID',\n            'SeriesNumber',\n            'SliceLocation',\n            'SliceThickness',\n            'SpacingBetweenSlices',\n            'SpatialResolution',\n            'SpecificCharacterSet',\n            'StudyInstanceUID',\n            'TemporalResolution',\n            'TransferSyntaxUID',\n            'TriggerWindow',\n            'WindowCenter',\n            'WindowWidth'\n        ]\n\n        self.fm_fields = [\n            'FileMetaInformationGroupLength',\n            'FileMetaInformationVersion',\n            'ImplementationClassUID',\n            'ImplementationVersionName',\n            'MediaStorageSOPClassUID',\n            'MediaStorageSOPInstanceUID',\n            'SourceApplicationEntityTitle',\n            'TransferSyntaxUID',\n        ]\n\n        self.metadata = []\n\n\n    def get_meta_info(self, dicom):\n        row = {f: dicom.get(f) for f in self.fields}\n        row_fm = {f: dicom.file_meta.get(f) for f in self.fm_fields}\n        row_other = {\n            'is_original_encoding': dicom.is_original_encoding,\n            'is_implicit_VR': dicom.is_implicit_VR,\n            'is_little_endian': dicom.is_little_endian,\n            'timestamp': dicom.timestamp,\n        }\n        return {**row, **row_fm, **row_other}\n\n\n    def get_dicom_files(self, input_dir, ds='train'):\n        dicoms = []\n\n        for subdir, dirs, files in os.walk(f\"{input_dir}/{ds}\"):\n            for filename in files:\n                filepath = subdir + os.sep + filename\n\n                if filepath.endswith(\".dcm\"):\n                    dicoms.append(filepath)\n\n        return dicoms\n\n\n    def process_dicom(self, dicom_src):\n        dicom = pydicom.dcmread(dicom_src)\n        file_data = dicom_src.split(\"/\")\n        file_src = \"/\".join(file_data[-4:])\n\n        tmp = {\"BraTS21ID\": file_data[-3], \"dataset\": file_data[-4], \"type\": file_data[-2], \"dicom_src\": f\"./{file_src}\"}\n        tmp.update(self.get_meta_info(dicom))\n\n        return tmp\n\n\n    def update(self, res):\n        if res is not None:\n            self.metadata.append(res)\n\n    def error(self,e):\n        print(e)\n\n\n    def runner(self, input, output, dataset, debug=0):\n        \n        dicom_files = self.get_dicom_files(input, dataset)\n\n        if debug!=0:\n            for dicom_file in tqdm(dicom_files[:10]):\n                self.metadata.append(self.process_dicom(dicom_file))\n        else:\n            for dicom_file in tqdm(dicom_files):\n                self.metadata.append(self.process_dicom(dicom_file))\n\n        self.df = pd.DataFrame(self.metadata)\n\n    def exec(self, dataset,debug=0):\n        if(os.path.exists('./dicom_metadata.csv')):\n            self.df = pd.read_csv('./dicom_metadata.csv')\n        else:\n            self.runner('../input/rsna-miccai-brain-tumor-radiogenomic-classification/','./', dataset, debug)","metadata":{"execution":{"iopub.status.busy":"2021-08-26T03:33:59.088862Z","iopub.execute_input":"2021-08-26T03:33:59.089267Z","iopub.status.idle":"2021-08-26T03:33:59.110885Z","shell.execute_reply.started":"2021-08-26T03:33:59.089236Z","shell.execute_reply":"2021-08-26T03:33:59.109947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_train = Dicom()\ndicom_train.exec('train')","metadata":{"execution":{"iopub.status.busy":"2021-08-26T03:33:59.111952Z","iopub.execute_input":"2021-08-26T03:33:59.112432Z","iopub.status.idle":"2021-08-26T04:17:28.969003Z","shell.execute_reply.started":"2021-08-26T03:33:59.112383Z","shell.execute_reply":"2021-08-26T04:17:28.961595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_test = Dicom()\ndicom_test.exec('test')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_train.df.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-26T04:17:28.971162Z","iopub.status.idle":"2021-08-26T04:17:28.971862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_test.df.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-26T04:17:28.973306Z","iopub.status.idle":"2021-08-26T04:17:28.974017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.concat([dicom_train.df,dicom_test.df]).to_csv('./dicom_metadata.csv',index=False)","metadata":{},"execution_count":null,"outputs":[]}]}