{"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":"# Fracture Detection\n\nThe goal of this competition is to identify fractures in CT scans of the cervical spine at both the level of a single vertebrae and the entire patient.\n\nQuickly detecting and determining the location of any vertebral fractures is essential to prevent neurologic deterioration and paralysis after trauma.","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"import pkgutil\n\ncheck_module = True if pkgutil.find_loader('hydra') else False\n\nif not check_module:\n    import subprocess    \n    subprocess.run('python -m pip install --no-index --find-links=../input/dependencies python-gdcm'.split())\n    subprocess.run('python -m pip install --no-index --find-links=../input/dependencies pylibjpeg'.split())\n    subprocess.run('python -m pip install --no-index --find-links=../input/dependencies pylibjpeg-libjpeg'.split())\nelse:\n    print('Environment is already setup')\n\ndel check_module","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport gdcm\nimport math\nimport matplotlib\nimport matplotlib.pyplot as pyplot\nimport nibabel\nimport numpy\nimport os\nimport pandas\nimport pydicom\nimport tensorflow\n\nclass FractureDetection:\n    \"\"\"\n    TODO: docstring\n    \"\"\"\n    def __init__(self):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        self.data_path = '../input/rsna-2022-cervical-spine-fracture-detection'\n        self.image_size = 50 # pixels\n        self.slice_count = 20\n\n    def return_slices(self, images_path, uid):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        full_path = os.path.join(self.data_path, images_path, uid)\n        slices = [pydicom.read_file(full_path + '/' + s) for s in os.listdir(full_path)]\n        slices.sort(key=lambda x: int(x.ImagePositionPatient[2]))\n        return slices","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TrainDataAnalysis(FractureDetection):\n    \"\"\"\n    TODO: docstring\n    \"\"\"\n    def __init__(self, labels_path, index_col):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        super().__init__()\n        self.labels = pandas.read_csv(os.path.join(\n            self.data_path, labels_path), index_col=index_col)\n        self.seg_image = nibabel.load(os.path.join(\n            self.data_path, 'segmentations/1.2.826.0.1.3680043.10633.nii'))\n        self.seg_data = self.seg_image.get_fdata()\n\n    def mean(self, l):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        return sum(l)/len(l)\n    \n    def resize_images(self, slices):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        slices = [cv2.resize(\n            numpy.array(s.pixel_array),\n            (self.image_size, self.image_size)) for s in slices]\n        return slices\n\n    def stack_slices(self, slices):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        slices = self.resize_images(slices)\n        chunk_size = math.floor(len(slices)/self.slice_count)\n        slices = slices[:chunk_size*self.slice_count]\n        stacked_slices = []\n        for i in range(0, len(slices), chunk_size):\n            chunk = slices[i:i+chunk_size]\n            chunk = list(map(self.mean, zip(*chunk)))\n            stacked_slices.append(chunk)\n        return len(slices), numpy.array(stacked_slices)\n\n    def yield_slices(self, stop_index, images_path):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        for uid in self.labels.index[0:stop_index]:\n            slices = self.return_slices(images_path, uid)\n            yield slices","metadata":{"_kg_hide-input":false,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"train_data_analysis = TrainDataAnalysis('train.csv', 0)","metadata":{}},{"cell_type":"markdown","source":"\nfor slices in train_data_analysis.yield_slices(1, 'train_images'):\n    print(slices[0].pixel_array.shape, len(slices))","metadata":{}},{"cell_type":"markdown","source":"for slices in train_data_analysis.yield_slices(1, 'train_images'):\n    print(slices[0])","metadata":{}},{"cell_type":"markdown","source":"for slices in train_data_analysis.yield_slices(1, 'train_images'):\n    pyplot.imshow(slices[0].pixel_array)\n    pyplot.show()","metadata":{}},{"cell_type":"markdown","source":"for slices in train_data_analysis.yield_slices(1, 'train_images'):\n    figure = pyplot.figure()\n    for i, s in enumerate(slices[:train_data_analysis.slice_count]):\n        y = figure.add_subplot(4, 5, i+1)\n        y.imshow(s.pixel_array)\n    pyplot.show()","metadata":{"_kg_hide-output":false}},{"cell_type":"markdown","source":"\"\"\"\nchunk slices into equal amounts\n\"\"\"\nfor slices in train_data_analysis.yield_slices(10, 'train_images'):\n    initial_length = len(slices)\n    resized_length, stacked_slices = train_data_analysis.stack_slices(slices)\n    print(initial_length, resized_length, len(stacked_slices))","metadata":{}},{"cell_type":"markdown","source":"for slices in train_data_analysis.yield_slices(1, 'train_images'):\n    _, stacked_slices = train_data_analysis.stack_slices(slices)\n    pyplot.imshow(stacked_slices[0])\n    pyplot.show()","metadata":{}},{"cell_type":"markdown","source":"for slices in train_data_analysis.yield_slices(1, 'train_images'):\n    _, stacked_slices = train_data_analysis.stack_slices(slices)\n    pyplot.imshow(stacked_slices[0], cmap='gray')\n    pyplot.show()","metadata":{}},{"cell_type":"markdown","source":"slices = train_data_analysis.return_slices('train_images', '1.2.826.0.1.3680043.10051')\npyplot.imshow(slices[132].pixel_array)\npyplot.gca().add_patch(matplotlib.patches.Rectangle(\n    (219.28, 216.71), 17.3, 20.39, linewidth=1, edgecolor='r', facecolor='none'))\npyplot.show()","metadata":{}},{"cell_type":"markdown","source":"print(train_data_analysis.seg_image.header)","metadata":{}},{"cell_type":"markdown","source":"print(train_data_analysis.seg_image.affine)","metadata":{}},{"cell_type":"markdown","source":"pyplot.imshow(train_data_analysis.seg_data[:,:,59])\npyplot.show()","metadata":{}},{"cell_type":"markdown","source":"class Preprocessing(TrainDataAnalysis):\n    \"\"\"\n    TODO: docstring\n    \"\"\"\n    def __init__(self, labels_path, index_col):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        super().__init__(labels_path, index_col)\n\n    def preprocess_image_data(self, stop_index, images_path):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        data = []\n        for i, slices in enumerate(self.yield_slices(stop_index, images_path)):\n            if i % (stop_index/10) == 0: print(i)\n            _, slices = self.stack_slices(slices)\n            slices = numpy.moveaxis(slices, 0, -1)\n            data.append(slices)\n        return data\n\n    def preprocess_label_data(self, stop_index):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        data = []\n        for i, uid in enumerate(self.labels.index[0:stop_index]):\n            if i % (stop_index/10) == 0: print(i)\n            labels = []\n            labels.append(self.labels.at[uid, 'C1'])\n            labels.append(self.labels.at[uid, 'C2'])\n            labels.append(self.labels.at[uid, 'C3'])\n            labels.append(self.labels.at[uid, 'C4'])\n            labels.append(self.labels.at[uid, 'C5'])\n            labels.append(self.labels.at[uid, 'C6'])\n            labels.append(self.labels.at[uid, 'C7'])\n            data.append(numpy.array(labels))\n        return data\n\n    def preprocess_label_data_overall(self, stop_index):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        data = []\n        for i, uid in enumerate(self.labels.index[0:stop_index]):\n            if i % (stop_index/10) == 0: print(i)\n            label = self.labels.at[uid, 'patient_overall']\n            if label == 0:\n                data.append(numpy.array([1, 0]))\n            else:\n                data.append(numpy.array([0, 1]))\n        return data","metadata":{"execution":{"iopub.status.busy":"2022-10-27T01:28:01.516032Z","iopub.execute_input":"2022-10-27T01:28:01.516489Z","iopub.status.idle":"2022-10-27T01:28:01.533455Z","shell.execute_reply.started":"2022-10-27T01:28:01.516459Z","shell.execute_reply":"2022-10-27T01:28:01.531773Z"}}},{"cell_type":"markdown","source":"preprocessing = Preprocessing('train.csv', 0)\n\nstop_index = 1000\nimage_data = preprocessing.preprocess_image_data(stop_index, 'train_images')\nlabel_data = preprocessing.preprocess_label_data(stop_index)\n\ndata = []\nfor i, l in zip(image_data, label_data):\n    data.append([i, l])\n\nnumpy.save('fracture_dataset.npy', numpy.asarray(data, dtype=object))","metadata":{"_kg_hide-output":false}},{"cell_type":"markdown","source":"class Training(FractureDetection):\n    \"\"\"\n    TODO: docstring\n    \"\"\"\n    def __init__(self):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        super().__init__()\n        \n    def construct_neural_network(self):\n        \"\"\"\n        TODO: docstring\n        \"\"\"\n        inputs = tensorflow.keras.Input(shape=(50, 50, 20))\n        x = tensorflow.keras.layers.Reshape((50, 50, 20, 1))(inputs)\n        x = tensorflow.keras.layers.Conv3D(\n            32, 3, padding='same', activation='relu', input_shape=(3, 3, 3, 1))(x)\n        x = tensorflow.keras.layers.MaxPool3D(strides=(2, 2, 2), padding='same')(x)\n        x = tensorflow.keras.layers.Conv3D(\n            64, 3, padding='same', activation='relu', input_shape=(3, 3, 3, 32))(x)\n        x = tensorflow.keras.layers.MaxPool3D(strides=(2, 2, 2), padding='same')(x)\n        x = tensorflow.keras.layers.Reshape((-1, 54080))(x)\n        x = tensorflow.keras.layers.Dense(1024, activation='relu')(x)\n        x = tensorflow.keras.layers.Dropout(0.8)(x)\n        outputs = tensorflow.keras.layers.Dense(7)(x)\n        model = tensorflow.keras.Model(inputs, outputs)\n        return model","metadata":{"_kg_hide-output":false}},{"cell_type":"markdown","source":"dataset = numpy.load('../input/fracture-dataset-a/fracture_dataset-a.npy', allow_pickle=True)\n\ntrain_data = dataset[0:800]\nval_data = dataset[800:900]\ntest_data = dataset[900:1000]\n\nx_train, y_train = [], []\nfor x, y in train_data:\n    x_train.append(x)\n    y_train.append(y)\n\nx_test, y_test = [], []\nfor x, y in test_data:\n    x_test.append([x])\n    y_test.append([[y]])\n\ntrain_data = tensorflow.data.Dataset.from_tensor_slices((x_train, y_train))\ntest_data = tensorflow.data.Dataset.from_tensor_slices((x_test, y_test))\nloss_fn = tensorflow.keras.losses.CategoricalCrossentropy(from_logits=True)\noptimizer = tensorflow.keras.optimizers.Adam()\ntraining = Training()\nmodel = training.construct_neural_network()\nmodel.compile(optimizer=optimizer, loss=loss_fn, metrics=['accuracy'])\n\nfor epoch in range(10):\n    print('epoch {} started'.format(epoch))\n    for x, y in train_data:\n        with tensorflow.GradientTape() as tape:\n            inputs = tensorflow.expand_dims(x, axis=0)\n            predictions = model(inputs, training=True)\n            predictions = tensorflow.squeeze(predictions)\n            loss = loss_fn(y, predictions)\n        gradients = tape.gradient(loss, model.trainable_variables)\n        optimizer.apply_gradients(zip(gradients, model.trainable_variables))\nloss, acc = model.evaluate(test_data)\nprint('loss {}, accuracy {}'.format(loss, acc))\n\nmodel.save('fracture_model.h5')","metadata":{}},{"cell_type":"code","source":"fracture_detection = FractureDetection()\nlabels = pandas.read_csv(os.path.join(fracture_detection.data_path, 'test.csv'), index_col=1)\nmodel = tensorflow.keras.models.load_model('../input/fracture-model-a/fracture_model-a.h5')\nrows, outputs = [], []\nfor uid in os.listdir(os.path.join(fracture_detection.data_path, 'test_images')):\n    try:\n        slices = fracture_detection.return_slices('test_images', uid)\n        _, slices = TrainDataAnalysis('test.csv', -1).stack_slices(slices)\n        slices = numpy.moveaxis(slices, 0, -1)\n        output = model.predict(tensorflow.expand_dims(slices, axis=0))\n        case = labels.at[uid, 'prediction_type']\n        if case == 'C1': output = output[0][0][0]\n        elif case == 'C2': output = output[0][0][1]\n        elif case == 'C3': output = output[0][0][2]\n        elif case == 'C4': output = output[0][0][3]\n        elif case == 'C5': output = output[0][0][4]\n        elif case == 'C6': output = output[0][0][5]\n        elif case == 'C7': output = output[0][0][6]\n        rows.append(labels.at[uid, 'row_id'])\n        outputs.append(output)\n    except:\n        pass\npredictions = pandas.DataFrame(list(zip(rows, outputs)), columns=['row_id', 'fractured'])\npredictions.to_csv('submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}