{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!cp ../input/gdcm-conda-install/gdcm.tar .\n!tar -xvzf gdcm.tar\n!conda install --offline ./gdcm/gdcm-2.8.9-py37h71b2a6d_0.tar.bz2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install -q ../input/monai030/monai-0.3.0-202010042353-py3-none-any.whl","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"! tar xvf ../input/rsna-src/workdir.tar_ ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport os\nos.makedirs(\"cache\", exist_ok=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"! python3 ./sub_b3_monai_position_1026_ensemble.py  --mode private   --skip","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"! mv submission.csv submission_pre.csv","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# requirement"},{"metadata":{"trusted":true},"cell_type":"code","source":"sub = pd.read_csv(\"./submission_pre.csv\")\ntest = pd.read_csv(\"../input/rsna-str-pulmonary-embolism-detection/test.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sub","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def check_consistency(sub, test):\n    \n    '''\n    Checks label consistency and returns the errors\n    \n    Args:\n    sub   = submission dataframe (pandas)\n    test  = test.csv dataframe (pandas)\n    '''\n    \n    # EXAM LEVEL\n    for i in test['StudyInstanceUID'].unique():\n        df_tmp = sub.loc[sub.id.str.contains(i, regex = False)].reset_index(drop = True)\n        df_tmp['StudyInstanceUID'] = df_tmp['id'].str.split('_').str[0]\n        df_tmp['label_type']       = df_tmp['id'].str.split('_').str[1:].apply(lambda x: '_'.join(x))\n        del df_tmp['id']\n        if i == test['StudyInstanceUID'].unique()[0]:\n            df = df_tmp.copy()\n        else:\n            df = pd.concat([df, df_tmp], axis = 0)\n    df_exam = df.pivot(index = 'StudyInstanceUID', columns = 'label_type', values = 'label')\n    \n    # IMAGE LEVEL\n    df_image = sub.loc[sub.id.isin(test.SOPInstanceUID)].reset_index(drop = True)\n    df_image = df_image.merge(test, how = 'left', left_on = 'id', right_on = 'SOPInstanceUID')\n    df_image.rename(columns = {\"label\": \"pe_present_on_image\"}, inplace = True)\n    del df_image['id']\n    \n    # MERGER\n    df = df_exam.merge(df_image, how = 'left', on = 'StudyInstanceUID')\n    ids    = ['StudyInstanceUID', 'SeriesInstanceUID', 'SOPInstanceUID']\n    labels = [c for c in df.columns if c not in ids]\n    df = df[ids + labels]\n    \n    # SPLIT NEGATIVE AND POSITIVE EXAMS\n    df['positive_images_in_exam'] = df['StudyInstanceUID'].map(df.groupby(['StudyInstanceUID']).pe_present_on_image.max())\n    df_pos = df.loc[df.positive_images_in_exam >  0.5]\n    df_neg = df.loc[df.positive_images_in_exam <= 0.5]\n    \n    # CHECKING CONSISTENCY OF POSITIVE EXAM LABELS\n    rule1a = df_pos.loc[((df_pos.rv_lv_ratio_lt_1  >  0.5)  & \n                         (df_pos.rv_lv_ratio_gte_1 >  0.5)) | \n                        ((df_pos.rv_lv_ratio_lt_1  <= 0.5)  & \n                         (df_pos.rv_lv_ratio_gte_1 <= 0.5))].reset_index(drop = True)\n    rule1a['broken_rule'] = '1a'\n    rule1b = df_pos.loc[(df_pos.central_pe    <= 0.5) & \n                        (df_pos.rightsided_pe <= 0.5) & \n                        (df_pos.leftsided_pe  <= 0.5)].reset_index(drop = True)\n    rule1b['broken_rule'] = '1b'\n    rule1c = df_pos.loc[(df_pos.acute_and_chronic_pe > 0.5) & \n                        (df_pos.chronic_pe           > 0.5)].reset_index(drop = True)\n    rule1c['broken_rule'] = '1c'\n    rule1d = df_pos.loc[(df_pos.indeterminate        > 0.5) | \n                        (df_pos.negative_exam_for_pe > 0.5)].reset_index(drop = True)\n    rule1d['broken_rule'] = '1d'\n\n    # CHECKING CONSISTENCY OF NEGATIVE EXAM LABELS\n    rule2a = df_neg.loc[((df_neg.indeterminate        >  0.5)  & \n                         (df_neg.negative_exam_for_pe >  0.5)) | \n                        ((df_neg.indeterminate        <= 0.5)  & \n                         (df_neg.negative_exam_for_pe <= 0.5))].reset_index(drop = True)\n    rule2a['broken_rule'] = '2a'\n    rule2b = df_neg.loc[(df_neg.rv_lv_ratio_lt_1     > 0.5) | \n                        (df_neg.rv_lv_ratio_gte_1    > 0.5) |\n                        (df_neg.central_pe           > 0.5) | \n                        (df_neg.rightsided_pe        > 0.5) | \n                        (df_neg.leftsided_pe         > 0.5) |\n                        (df_neg.acute_and_chronic_pe > 0.5) | \n                        (df_neg.chronic_pe           > 0.5)].reset_index(drop = True)\n    rule2b['broken_rule'] = '2b'\n    \n    # MERGING INCONSISTENT PREDICTIONS\n    errors = pd.concat([rule1a, rule1b, rule1c, rule1d, rule2a, rule2b], axis = 0)\n    \n    # OUTPUT\n    print('Found', len(errors), 'inconsistent predictions')\n    return errors","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"check_consistency(sub.copy(), test.copy())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# EXAM LEVEL\nfor i in test['StudyInstanceUID'].unique():\n\n    df_tmp = sub.loc[sub.id.str.contains(i, regex = False)].reset_index(drop = True)\n    df_tmp['StudyInstanceUID'] = df_tmp['id'].str.split('_').str[0]\n    df_tmp['label_type']       = df_tmp['id'].str.split('_').str[1:].apply(lambda x: '_'.join(x))\n    del df_tmp['id']\n\n    if i == test['StudyInstanceUID'].unique()[0]:\n        df = df_tmp.copy()\n    else:\n        df = pd.concat([df, df_tmp], axis = 0)\n\ndf_exam = df.pivot(index = 'StudyInstanceUID', columns = 'label_type', values = 'label')\n\n\n# IMAGE LEVEL\ndf_image = sub.loc[sub.id.isin(test.SOPInstanceUID)].reset_index(drop = True)\ndf_image = df_image.merge(test, how = 'left', left_on = 'id', right_on = 'SOPInstanceUID')\ndf_image.rename(columns = {\"label\": \"pe_present_on_image\"}, inplace = True)\ndel df_image['id']\n\n# MERGER\ndf = df_exam.merge(df_image, how = 'left', on = 'StudyInstanceUID')\nids    = ['StudyInstanceUID', 'SeriesInstanceUID', 'SOPInstanceUID']\nlabels = [c for c in df.columns if c not in ids]\ndf = df[ids + labels]\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tqdm import tqdm\nimport numpy as np","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#%%capture\n\nupper_bound = 0.500001\nlower_bound = 0.499999\n\nfor i in tqdm(df.StudyInstanceUID.unique()):\n    sel = df[df.StudyInstanceUID == i].copy().reset_index(drop = True)\n    \n    #adjust exam level predictions\n\n    image_level_bool = (sel.pe_present_on_image > 0.5).any()\n\n    if(image_level_bool):\n        #print(\"exam has positive images adjust exam\")\n        ############ \n        #Negative_Exam\n        ############\n\n        # if one image is positive, exam has to be positive\n        old_negative_exam_for_pe = sel.negative_exam_for_pe[0]\n        new_negative_exam_for_pe = np.clip(old_negative_exam_for_pe, 0, lower_bound)\n\n\n        ############ \n        #Position\n        ############\n\n        # atleast one of rightsided, leftsided, central has to be > 0.5\n        old_rightsided_pe = sel.rightsided_pe[0]\n        old_leftsided_pe = sel.leftsided_pe[0]\n        old_central_pe = sel.central_pe[0]\n\n        position_arr = np.array([old_rightsided_pe, old_leftsided_pe, old_central_pe])\n\n        if((position_arr > 0.5).any()):\n            print()\n        else:\n            #adjust the one which has the highest value          \n            position_arr[np.argmin((0.5 - position_arr) * (0.0625, 0.0625 ,0.1877))] = upper_bound\n\n        ############ \n        #RV_LV\n        ############\n\n        old_rv_lv_ratio_gte_1 = sel.rv_lv_ratio_gte_1[0]\n        old_rv_lv_ratio_lt_1 = sel.rv_lv_ratio_lt_1[0]\n\n        rv_lv_arr = np.array([old_rv_lv_ratio_lt_1, old_rv_lv_ratio_gte_1])\n\n\n        #only one can be > 0.5\n        #adjust the one which is lower\n        if((rv_lv_arr > 0.5).all()):\n            rv_lv_arr[np.argmin((rv_lv_arr - 0.5) * (0.0782, 0.2346))] = lower_bound\n\n\n        #one has to be > 0.5\n        #adjust the one which has the highest value\n        elif((rv_lv_arr < 0.5).all()):\n            rv_lv_arr[np.argmin((0.5 - rv_lv_arr) * (0.0782, 0.2346))] = upper_bound\n            \n        #print(rv_lv_arr)\n\n        ############ \n        #ACUTE & CHRONIC\n        ############\n        # one of acute_and_chronic_pe or chronic_pe has to be > 0.5\n        old_acute_and_chronic_pe = sel.acute_and_chronic_pe[0]\n        old_chronic_pe = sel.chronic_pe[0]\n        #\n        acute_chronic_arr = np.array([old_acute_and_chronic_pe, old_chronic_pe])\n\n        if((acute_chronic_arr > 0.5).all()):\n            acute_chronic_arr[np.argmin((acute_chronic_arr - 0.5) * (0.104294, 0.104294))] = lower_bound\n\n        #print(\"Position\", position_arr)\n        #print(\"RV_LV\", rv_lv_arr)\n        #print(\"ACUTE/CHRONIC\", acute_chronic_arr)\n\n\n        if(~((acute_chronic_arr == np.array([old_acute_and_chronic_pe, old_chronic_pe])).all())):\n            print(\"ACUTE/CHRONIC changed\")\n\n        if(~((rv_lv_arr == np.array([old_rv_lv_ratio_lt_1, old_rv_lv_ratio_gte_1])).all())):\n            print(\"RVLV changed\")\n\n        if(~((position_arr == np.array([old_rightsided_pe, old_leftsided_pe, old_central_pe])).all())):\n            print(\"POSITION changed\")\n            \n        print(i, acute_chronic_arr, rv_lv_arr, position_arr)\n\n    else:\n        #print(\"exam has no positive images adjust exam\")\n\n        ############ \n        #Negative_Exam\n        ############\n\n        # if one image is positive, exam has to be positive\n        old_negative_exam_for_pe = sel.negative_exam_for_pe[0]\n        new_negative_exam_for_pe = np.clip(old_negative_exam_for_pe, upper_bound, 1)\n\n\n        ############ \n        #Position\n        ############\n\n        # atleast one of rightsided, leftsided, central has to be > 0.5\n        old_rightsided_pe = sel.rightsided_pe[0]\n        old_leftsided_pe = sel.leftsided_pe[0]\n        old_central_pe = sel.central_pe[0]\n\n        position_arr = np.array([old_rightsided_pe, old_leftsided_pe, old_central_pe])\n        position_arr = np.clip(position_arr, 0, lower_bound)\n\n        ############ \n        #RV_LV\n        ############\n\n\n        old_rv_lv_ratio_gte_1 = sel.rv_lv_ratio_gte_1[0]\n        old_rv_lv_ratio_lt_1 = sel.rv_lv_ratio_lt_1[0]\n\n        rv_lv_arr = np.array([old_rv_lv_ratio_lt_1, old_rv_lv_ratio_gte_1])\n        rv_lv_arr = np.clip(rv_lv_arr, 0, lower_bound)\n\n        ############ \n        #ACUTE & CHRONIC\n        ############\n\n\n        # one of acute_and_chronic_pe or chronic_pe has to be > 0.5\n        old_acute_and_chronic_pe = sel.acute_and_chronic_pe[0]\n        old_chronic_pe = sel.chronic_pe[0]\n        #\n        acute_chronic_arr = np.array([old_acute_and_chronic_pe, old_chronic_pe])\n        acute_chronic_arr = np.clip(acute_chronic_arr, 0, lower_bound)\n\n        #print(\"Position\", position_arr)\n        #print(\"RV_LV\", rv_lv_arr)\n        #print(\"ACUTE/CHRONIC\", acute_chronic_arr)\n\n        if(~((acute_chronic_arr == np.array([old_acute_and_chronic_pe, old_chronic_pe])).all())):\n            print(\"ACUTE/CHRONIC changed\")\n\n        if(~((rv_lv_arr == np.array([old_rv_lv_ratio_lt_1, old_rv_lv_ratio_gte_1])).all())):\n            print(\"RVLV changed\")\n\n        if(~((position_arr == np.array([old_rightsided_pe, old_leftsided_pe, old_central_pe])).all())):\n            print(\"POSITION changed\")\n            \n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_negative_exam_for_pe\"] = new_negative_exam_for_pe\n\n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_rightsided_pe\"] = position_arr[0]\n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_leftsided_pe\"] = position_arr[1]\n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_central_pe\"] = position_arr[2]\n\n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_rv_lv_ratio_lt_1\"] = rv_lv_arr[0]\n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_rv_lv_ratio_gte_1\"] = rv_lv_arr[1]\n    \n    print(i, sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_rv_lv_ratio_lt_1\"], sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_rv_lv_ratio_gte_1\"])\n    \n    sub[\"label\"][sub.id == sel.StudyInstanceUID[0] + \"_indeterminate\"] = np.clip(sel.indeterminate[0], 0, 0.5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"check = check_consistency(sub, test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(check)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if(len(check) == 0):\n    sub.to_csv(\"submission.csv\", index = False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}