kidcoconut commited on
Commit
48f39fa
β€’
1 Parent(s): 09fd2b4

DEPLOY: updated all files for manual deploy to huggingface

Browse files
Files changed (37) hide show
  1. .dockerignore +10 -6
  2. .gitattributes +9 -2
  3. .gitignore +40 -4
  4. README.md +1 -1
  5. app.py +6 -9
  6. data/demo_tiles/raw/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10752_30720.tiff +0 -3
  7. data/demo_tiles/raw/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0144_svsvt_chunks_36864_4608.tiff +0 -3
  8. data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_30720.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsvt_chunks_10240_13312.tiff} +1 -1
  9. data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_31232.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svswt_chunks_38912_5632.tiff} +1 -1
  10. data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_31744.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0140_svsvt_chunks_45056_8192.tiff} +1 -1
  11. data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_32256.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0141_svsvt_chunks_39936_26624.tiff} +1 -1
  12. data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0141_svswt_chunks_46080_46080.tiff +3 -0
  13. data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0142_svswt_chunks_41472_21504.tiff +3 -0
  14. data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0145_svsvt_chunks_5632_28672.tiff +3 -0
  15. data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0161_svsvt_chunks_37888_35840.tiff +3 -0
  16. data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0161_svsvt_chunks_44032_38912.tiff +3 -0
  17. data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0161_svswt_chunks_46080_19456.tiff +3 -0
  18. lib/models/__init__.py +0 -0
  19. lib/models/mdl_autoenc.py +55 -0
  20. lib/models/mdl_kmeans.py +155 -0
  21. lib/models/mdl_logR.py +41 -0
  22. lib/models/mdl_svm.py +40 -0
  23. lib/models/mdl_utils.py +256 -0
  24. lib/models/mdl_xgb.py +66 -0
  25. lib/utils.py +1 -0
  26. util_dockerPreRun.sh β†’ scripts/docker/util_docker_preRun.sh +17 -5
  27. scripts/docker/util_local_buildDockerDemo.sh +85 -0
  28. scripts/docker/util_local_runDockerDemo.sh +33 -0
  29. scripts/huggingface/util_local_readyDeploy_toHugSpace_streamlit.sh +88 -0
  30. {bin β†’ scripts}/models/util_joinModel.sh +14 -1
  31. {bin β†’ scripts}/models/util_splitModel.sh +14 -1
  32. util_startLocal_streamlitFastApi.sh β†’ scripts/streamlitFastApi/util_local_runStreamlitFastApi.sh +10 -6
  33. scripts/util.sh +148 -0
  34. uix/lit_sidebar.py +8 -61
  35. uix/pages/lit_about.py +9 -5
  36. uix/pages/lit_diagnosis.py +91 -25
  37. uix/pages/lit_home.py +57 -13
.dockerignore CHANGED
@@ -1,17 +1,21 @@
1
 
 
2
  #--- ignore select binary files/folders
3
  bin/images/sample*
4
  bin/models/*.pth
5
  bin/models/*.zip
 
6
  bin/testing
7
-
 
 
8
 
9
  #--- ignore all local data files; preserve/recreate folder structure
10
- data_host_mount
11
  data/tiles
12
  data/wsi
13
 
14
-
15
- #--- ignore all files within the _ignore folder
16
- _ignore
17
-
 
1
 
2
+
3
  #--- ignore select binary files/folders
4
  bin/images/sample*
5
  bin/models/*.pth
6
  bin/models/*.zip
7
+ bin/models/deeplabv3*vhflip30/*.pth
8
  bin/testing
9
+ _ignore
10
+ .vscode
11
+ cicd_workflows
12
 
13
  #--- ignore all local data files; preserve/recreate folder structure
14
+ data/demo_tiles/*.tiff
15
  data/tiles
16
  data/wsi
17
 
18
+ #--- ignore all doc files
19
+ docs
20
+ notebooks
21
+ preso
.gitattributes CHANGED
@@ -1,3 +1,10 @@
 
 
 
 
 
 
 
1
  *.7z filter=lfs diff=lfs merge=lfs -text
2
  *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
@@ -23,7 +30,6 @@
23
  *.pth filter=lfs diff=lfs merge=lfs -text
24
  *.rar filter=lfs diff=lfs merge=lfs -text
25
  *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
  *.tar.* filter=lfs diff=lfs merge=lfs -text
28
  *.tar filter=lfs diff=lfs merge=lfs -text
29
  *.tflite filter=lfs diff=lfs merge=lfs -text
@@ -33,7 +39,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
- *model_a* filter=lfs diff=lfs merge=lfs -text
37
  *.tiff filter=lfs diff=lfs merge=lfs -text
38
  data/demo_tiles/raw/*.tiff filter=lfs diff=lfs merge=lfs -text
39
  bin/models/deeplabv3*vhflip30/model_a* filter=lfs diff=lfs merge=lfs -text
 
 
 
1
+ #--- Note: omdena github does not allow git lfs. Disable.
2
+ #--- Note: huggingface does not allow _any_ binaries; git lfs has to be used
3
+ #bin/models/*.pth filter=lfs diff=lfs merge=lfs -text
4
+ #bin/models/deeplab*vhflip30/model_a* filter=lfs diff=lfs merge=lfs -text
5
+ #bin/images/* filter=lfs diff=lfs merge=lfs -text
6
+ #data/demo_tiles/raw/* filter=lfs diff=lfs merge=lfs -text
7
+
8
  *.7z filter=lfs diff=lfs merge=lfs -text
9
  *.arrow filter=lfs diff=lfs merge=lfs -text
10
  *.bin filter=lfs diff=lfs merge=lfs -text
 
30
  *.pth filter=lfs diff=lfs merge=lfs -text
31
  *.rar filter=lfs diff=lfs merge=lfs -text
32
  *.safetensors filter=lfs diff=lfs merge=lfs -text
 
33
  *.tar.* filter=lfs diff=lfs merge=lfs -text
34
  *.tar filter=lfs diff=lfs merge=lfs -text
35
  *.tflite filter=lfs diff=lfs merge=lfs -text
 
39
  *.zip filter=lfs diff=lfs merge=lfs -text
40
  *.zst filter=lfs diff=lfs merge=lfs -text
41
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
42
  *.tiff filter=lfs diff=lfs merge=lfs -text
43
  data/demo_tiles/raw/*.tiff filter=lfs diff=lfs merge=lfs -text
44
  bin/models/deeplabv3*vhflip30/model_a* filter=lfs diff=lfs merge=lfs -text
45
+ *model_a* filter=lfs diff=lfs merge=lfs -text
46
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
.gitignore CHANGED
@@ -1,13 +1,49 @@
 
 
 
 
1
  #--- specific to task5-deploy
2
  bin/images/sample*
3
- bin/models/*/*.pth
4
- bin/models/*.pth
5
- bin/models/*.zip
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  bin/testing
 
 
 
 
 
 
 
 
 
7
  data/tiles
8
  data/wsi
9
  data_host_mount
 
 
 
 
10
  _ignore
 
 
 
11
 
12
 
13
  # Byte-compiled / optimized / DLL files
@@ -26,7 +62,7 @@ dist/
26
  downloads/
27
  eggs/
28
  .eggs/
29
- lib/
30
  lib64/
31
  parts/
32
  sdist/
 
1
+ #--- NOTE: this .gitignore is specific to the hugspace_docker cicd deploy
2
+ #--- WARN: omdena github does not support git lfs at all; allows small binary files
3
+ #--- WARN: huggingface github does not allow _any_ binary files outside of git lfs
4
+
5
  #--- specific to task5-deploy
6
  bin/images/sample*
7
+ bin/images/dbl.png
8
+
9
+ #--- specific to cicd_hugspace_streamlit deploy
10
+ #--- omdena github will not have access to git lfs or the complete model file
11
+ #--- cicd will rebuild the model file
12
+ #.vscode
13
+ #bin/models/deeplabv3*vhflip30/*.pth
14
+ #bin/testing
15
+ #data/demo_tiles/raw/*.tiff
16
+ #notebooks
17
+ #.dockerignore
18
+ #Dockerfile
19
+ #main.py
20
+
21
+ #--- specific to cicd_hugspace_docker deploy
22
+ #--- omdena github will not have access to git lfs or the complete model file
23
+ #--- cicd will rebuild the model file
24
+ .vscode
25
+ bin/models/deeplabv3*vhflip30/*.pth
26
  bin/testing
27
+ data/demo_tiles/raw/*.tiff
28
+ notebooks
29
+
30
+
31
+ #--- omdena github does not allow large files or git lfs
32
+ bin/models/*.pth
33
+ bin/models/*.zip
34
+ #bin/models/deeplabv3*/model_a* #--- save partial model files in omdena github
35
+ #data/demo_tiles #--- allow demo tiles in the github for use and ref
36
  data/tiles
37
  data/wsi
38
  data_host_mount
39
+
40
+ preso
41
+
42
+ *.pth
43
  _ignore
44
+ *.bkp
45
+ *.dtmp
46
+ *.pptx
47
 
48
 
49
  # Byte-compiled / optimized / DLL files
 
62
  downloads/
63
  eggs/
64
  .eggs/
65
+ #lib/
66
  lib64/
67
  parts/
68
  sdist/
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Spcdkr Omdenasaudi Liverhccxai
3
  emoji: 🏒
4
  colorFrom: purple
5
  colorTo: green
 
1
  ---
2
+ title: spcDkr omdenaSaudi Liver HCC XAI
3
  emoji: 🏒
4
  colorFrom: purple
5
  colorTo: green
app.py CHANGED
@@ -2,7 +2,6 @@
2
  toExecute: (from root app folder) ... streamlit run app.py
3
  '''
4
  import streamlit as st
5
- #from uix import lit_sidebar as lit_sideBar
6
  import uix.lit_sidebar as litSideBar
7
 
8
 
@@ -11,16 +10,14 @@ st.set_page_config(
11
  page_title='Omdena Saudi Arabia - Liver HCC Diagnosis with XAI',
12
  #page_icon='https://cdn.freebiesupply.com/logos/thumbs/1x/nvidia-logo.png',
13
  layout="wide")
14
- st.header("Omdena Saudi Arabia - Liver HCC Diagnosis with XAI")
 
 
 
 
 
15
  st.markdown('---')
16
 
17
 
18
  #--- streamlit: add a sidebar
19
  litSideBar.init()
20
-
21
-
22
- #if __name__ == '__main__':
23
- # st.run("main:app", host="0.0.0.0", port=49300, reload=True)
24
- # streamlit run app.py --server.port 49400 --server.maxUploadSize 2000
25
-
26
- #aryPkg[moduleNames.index(page)].run()
 
2
  toExecute: (from root app folder) ... streamlit run app.py
3
  '''
4
  import streamlit as st
 
5
  import uix.lit_sidebar as litSideBar
6
 
7
 
 
10
  page_title='Omdena Saudi Arabia - Liver HCC Diagnosis with XAI',
11
  #page_icon='https://cdn.freebiesupply.com/logos/thumbs/1x/nvidia-logo.png',
12
  layout="wide")
13
+ st.header('\
14
+ Detecting Liver Cancer from Histopathology WSI \
15
+ using Deep Learning and Explainability (XAI)\
16
+ ')
17
+ st.markdown('#### Dr. Shaista Hussain (Saudi Arabia Chapter Lead)')
18
+ st.markdown("##### Iain McKone (Deployment Lead) [LinkedIn](%s)" % "https://linkedin.com/in/iainmckone")
19
  st.markdown('---')
20
 
21
 
22
  #--- streamlit: add a sidebar
23
  litSideBar.init()
 
 
 
 
 
 
 
data/demo_tiles/raw/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10752_30720.tiff DELETED

Git LFS Details

  • SHA256: 7028a7b0259f6b4ad827620204356e93c69c05c7bf1b2a93866b8523d8905738
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0144_svsvt_chunks_36864_4608.tiff DELETED

Git LFS Details

  • SHA256: cc0b0edae31020d7f4477d7eebe5a316794de2966ed4a129682b5b8831d01ca6
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_30720.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsvt_chunks_10240_13312.tiff} RENAMED
File without changes
data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_31232.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svswt_chunks_38912_5632.tiff} RENAMED
File without changes
data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_31744.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0140_svsvt_chunks_45056_8192.tiff} RENAMED
File without changes
data/demo_tiles/raw/{Dataset_PAIP2019_Omdena_Validation_Image_01_01_0105_svsbg_chunks_10240_32256.tiff β†’ sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0141_svsvt_chunks_39936_26624.tiff} RENAMED
File without changes
data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0141_svswt_chunks_46080_46080.tiff ADDED

Git LFS Details

  • SHA256: 384304ab2e113ef190b025a7706913f2dd305591aa262cb90fbdde4635c90bcc
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0142_svswt_chunks_41472_21504.tiff ADDED

Git LFS Details

  • SHA256: 57e67d534e0bce3f305fca0037b3e5b069dab0dd5b7100b259ae47c21d410345
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0145_svsvt_chunks_5632_28672.tiff ADDED

Git LFS Details

  • SHA256: 31d1a4b039f036a019f2a11e0f3c0002f9c83125b32c8a868aab4c5a996ce1ff
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0161_svsvt_chunks_37888_35840.tiff ADDED

Git LFS Details

  • SHA256: 02e14838208a8afa44c5d7a94a19e95b5ba348e4f243e2445cab00d2d0fe202c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0161_svsvt_chunks_44032_38912.tiff ADDED

Git LFS Details

  • SHA256: 6a004d358b77bcb115e7a7178e5cea2d11539076069fe557075a07913520db62
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
data/demo_tiles/raw/sample/Dataset_PAIP2019_Omdena_Validation_Image_01_01_0161_svswt_chunks_46080_19456.tiff ADDED

Git LFS Details

  • SHA256: 7450a97f433fda64a85e21883f9b53c9f38f36be18ead29aaac1ee03d6d096ff
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
lib/models/__init__.py ADDED
File without changes
lib/models/mdl_autoenc.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ from sklearn.decomposition import PCA
4
+ import lib.utils as libPaths
5
+ import pickle
6
+
7
+
8
+ m_kstrFile = __file__
9
+ m_kstrDataPath = libPaths.pth_data
10
+ m_kstrBinModelPath = libPaths.pth_binModels
11
+ m_kstrPcaModelPath = m_kstrBinModelPath + 'pca_unsuperv_colab.pkl'
12
+ m_kstrEncModelPath = m_kstrBinModelPath + 'enc_keras_seq/'
13
+
14
+
15
+ #--- Supervised: autoencoder - Principal Component Analysis
16
+ def load_encFromKeras():
17
+ from tensorflow import keras
18
+ mdlAnoms = keras.models.load_model(m_kstrEncModelPath)
19
+ return mdlAnoms
20
+
21
+
22
+ def load_pcaFromPkl():
23
+ with open(m_kstrPcaModelPath, 'rb') as filPkl:
24
+ # load using pickle de-serializer
25
+ mdlAnoms = pickle.load(filPkl)
26
+ return mdlAnoms
27
+
28
+
29
+ def save_encToKeras(mdlAnoms):
30
+ mdlAnoms.save(m_kstrEncModelPath)
31
+
32
+
33
+
34
+ def predict(pdfScaled):
35
+
36
+ #--- Pre: Transforming train and test dataframes based on PCA
37
+ mdlPCA = load_pcaFromPkl() #--- this is a pre-fit model based on training
38
+ npaPca = mdlPCA.transform(pdfScaled)
39
+ print("INFO (" + m_kstrFile + ".predict) npaPca.shape: ", npaPca.shape)
40
+
41
+
42
+ #--- predict on unseen data
43
+ mdlEnc = load_encFromKeras()
44
+ npaPredict = mdlEnc.predict(npaPca[:,:29])
45
+ print("INFO (" + m_kstrFile + ".predict) npaPredict.shape: ", npaPredict.shape)
46
+ #--- expected: 297, 29?
47
+ return npaPredict
48
+
49
+
50
+ """
51
+ def train(pdfTrainData):
52
+ mdlAnoms = PCA() #---- TODO: this is Keras Sequential
53
+ mdlAnoms.fit(pdfTrainData.values)
54
+ save_encToKeras(mdlAnoms)
55
+ return mdlAnoms """
lib/models/mdl_kmeans.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sklearn.cluster import KMeans
2
+ import lib.utils as libPaths
3
+ import pickle
4
+ import pandas as pd
5
+
6
+
7
+ m_kstrFile = __file__
8
+ m_kstrDataPath = libPaths.pth_data
9
+ m_kstrBinModelPath = libPaths.pth_binModels
10
+
11
+ #m_kstrPcaModelPath = m_kstrBinModelPath + 'pca_kmeans_unsuperv_colab.pkl'
12
+ #m_kstrPcaModelPath = m_kstrBinModelPath + 'pca_kmeans_unsuperv_colab_v1.2.1.pkl'
13
+ m_kstrPcaModelPath_111 = m_kstrBinModelPath + 'claims_pca_v1.1.1_27cols.pkl' #--- ERROR: __randomstate_ctor() takes from 0 to 1 positional arguments but 2 were given
14
+ m_kstrPcaModelPath_121 = m_kstrBinModelPath + 'claims_pca_v1.2.1_27cols.pkl'
15
+ m_kstrPcaModelPath_claims_py3816_sk111hp = m_kstrBinModelPath + 'claims_pca_py3816_sk111hp_27cols.pkl'
16
+ m_kstrPcaModelPath = m_kstrPcaModelPath_claims_py3816_sk111hp
17
+
18
+ #m_kstrKmeansModelPath = m_kstrBinModelPath + 'kmeans_unsuperv_colab.pkl'
19
+ #m_kstrKmeansModelPath = m_kstrBinModelPath + 'kmn_unsuperv_colab_v1.2.1.pkl'
20
+ m_kstrModelPath_111 = m_kstrBinModelPath + 'claims_kmn_v1.1.1_22cols.pkl' #--- ERROR: __randomstate_ctor() takes from 0 to 1 positional arguments but 2 were given
21
+ m_kstrModelPath_121 = m_kstrBinModelPath + 'claims_kmn_v1.2.1_22cols.pkl'
22
+ m_kstrModelPath_claims_py3816_sk111hp = m_kstrBinModelPath + 'claims_kmn_py3816_sk111hp_22cols.pkl'
23
+ m_kstrKmeansModelPath = m_kstrModelPath_claims_py3816_sk111hp
24
+
25
+ m_blnTraceOn = True
26
+
27
+
28
+ #--- unsupervised: Logistic Regession
29
+ def load_pcaFromPkl():
30
+ with open(m_kstrPcaModelPath, 'rb') as filPkl:
31
+ mdlAnoms = pickle.load(filPkl)
32
+ return mdlAnoms
33
+
34
+
35
+ #--- unsupervised: KMeans
36
+ def load_kmeansFromPkl():
37
+ with open(m_kstrKmeansModelPath, 'rb') as filPkl:
38
+ mdlAnoms = pickle.load(filPkl)
39
+ return mdlAnoms
40
+
41
+
42
+ def save_pcaToPkl(mdlAnoms):
43
+ with open(m_kstrPcaModelPath, 'wb') as filPkl:
44
+ pickle.dump(mdlAnoms, filPkl)
45
+ return mdlAnoms
46
+
47
+
48
+ def save_kmeansToPkl(mdlAnoms):
49
+ with open(m_kstrKmeansModelPath, 'wb') as filPkl:
50
+ pickle.dump(mdlAnoms, filPkl)
51
+ return mdlAnoms
52
+
53
+
54
+
55
+ #--- determine which points can be labelled against which clusters
56
+ def predict(pdfScaled):
57
+ #--- load a persisted fit kmeans model
58
+ #--- predict will assign labels onto a similarly scaled data frame
59
+
60
+
61
+ #--- Note: reverse chron through the code ...
62
+ #--- 4. KMeans was fit on X-reduced (22 cols)
63
+ #--- 3. X_reduced was a reduced column set of X-scaled (27 -> 22; Dropped 5 cols: DeadOrNot; and hotEncoded Gender and Race)
64
+ #--- 2. x_scaled was transformed through stdScaler
65
+ #--- 1. StdScaler was fit on X to produce X-scaled (X has 27 cols)
66
+ pdfReduced = pdfScaled[['InscClaimAmtReimbursed', 'DeductibleAmtPaid',
67
+ 'AdmittedDays', 'RenalDiseaseIndicator', 'NoOfMonths_PartACov',
68
+ 'NoOfMonths_PartBCov', 'ChronicCond_Alzheimer',
69
+ 'ChronicCond_Heartfailure', 'ChronicCond_KidneyDisease',
70
+ 'ChronicCond_Cancer', 'ChronicCond_ObstrPulmonary',
71
+ 'ChronicCond_Depression', 'ChronicCond_Diabetes',
72
+ 'ChronicCond_IschemicHeart', 'ChronicCond_Osteoporasis',
73
+ 'ChronicCond_rheumatoidarthritis', 'ChronicCond_stroke',
74
+ 'IPAnnualReimbursementAmt', 'IPAnnualDeductibleAmt',
75
+ 'OPAnnualReimbursementAmt', 'OPAnnualDeductibleAmt', 'Age']]
76
+
77
+ #--- prefit Kmeans clustering - was fit on trained pdfReduced
78
+ #--- Note: if we want to understand how kmeans performs on test/prod data, we need to predict
79
+ mdlKMeans = load_kmeansFromPkl()
80
+ #ndaPredict = mdlKMeans.predict(pdfScaled) #20230208: ValueError: X has 27 features, but KMeans is expecting 22 features as input.
81
+ ndaPredict = mdlKMeans.predict(pdfReduced) #ValueError: X has 22 features, but KMeans is expecting 27 features as input.
82
+ return ndaPredict
83
+
84
+
85
+ #--- feat eng
86
+ def do_featEng(pdfLoaded, blnIsTrain=False, hasGroupByProviderCols=True):
87
+ print("INFO (mdl_kmeans.doFeatEng): blnIsTrain, ", blnIsTrain)
88
+
89
+ #--- columns_to_remove
90
+ aryColsToDrop = ['BeneID', 'ClaimID', 'ClaimStartDt','ClaimEndDt','AttendingPhysician',
91
+ 'OperatingPhysician', 'OtherPhysician', 'ClmDiagnosisCode_1',
92
+ 'ClmDiagnosisCode_2', 'ClmDiagnosisCode_3', 'ClmDiagnosisCode_4',
93
+ 'ClmDiagnosisCode_5', 'ClmDiagnosisCode_6', 'ClmDiagnosisCode_7',
94
+ 'ClmDiagnosisCode_8', 'ClmDiagnosisCode_9', 'ClmDiagnosisCode_10',
95
+ 'ClmProcedureCode_1', 'ClmProcedureCode_2', 'ClmProcedureCode_3',
96
+ 'ClmProcedureCode_4', 'ClmProcedureCode_5', 'ClmProcedureCode_6',
97
+ 'ClmAdmitDiagnosisCode', 'AdmissionDt',
98
+ 'DischargeDt', 'DiagnosisGroupCode','DOB', 'DOD',
99
+ 'State', 'County']
100
+ pdfFeatEng = pdfLoaded.drop(columns=aryColsToDrop, axis=1)
101
+
102
+ #--- flag categorical cols
103
+ pdfFeatEng.Gender = pdfFeatEng.Gender.astype('category')
104
+ pdfFeatEng.Race = pdfFeatEng.Race.astype('category')
105
+
106
+ #--- one-hot-encoding
107
+ pdfFeatEng = pd.get_dummies(pdfFeatEng, columns=['Gender', 'Race'], drop_first=True)
108
+ if (blnIsTrain):
109
+ #--- one-hot encode the potential fraud column (for training data only)
110
+ try:
111
+ #print("INFO (claims.doFeatEng): one-hot encoding potential fraud")
112
+ pdfFeatEng.loc[pdfFeatEng['PotentialFraud'] == 'Yes', 'PotentialFraud'] = 1
113
+ pdfFeatEng.loc[pdfFeatEng['PotentialFraud'] == 'No', 'PotentialFraud'] = 0
114
+ except KeyError:
115
+ #--- likely column not found; invalid fxn call
116
+ print("ERROR (claims.doFeatEng): Potential Fraud col not found")
117
+
118
+ pdfFeatEng.loc[pdfFeatEng['RenalDiseaseIndicator'] == 'Y', 'RenalDiseaseIndicator'] = 1
119
+ pdfFeatEng['DeductibleAmtPaid'].fillna(0, inplace=True)
120
+ pdfFeatEng['AdmittedDays'].fillna(0, inplace=True)
121
+
122
+ #--- check for correlated cols
123
+
124
+ #--- add new features to assist with predictions
125
+ if (hasGroupByProviderCols):
126
+ pdfFeatEng['InscClaimReimbursement_ProviderAvg'] = pdfFeatEng.groupby(['Provider'])['InscClaimAmtReimbursed'].transform('mean')
127
+ pdfFeatEng['DeductibleAmtPaid_ProviderAvg'] = pdfFeatEng.groupby(['Provider'])['DeductibleAmtPaid'].transform('mean')
128
+
129
+ pdfFeatEng['IPAnnualReimbursementAmt_ProviderAvg'] = pdfFeatEng.groupby(['Provider'])['IPAnnualReimbursementAmt'].transform('mean')
130
+ pdfFeatEng['IPAnnualDeductibleAmt_ProviderAvg'] = pdfFeatEng.groupby(['Provider'])['IPAnnualDeductibleAmt'].transform('mean')
131
+
132
+ pdfFeatEng['OPAnnualReimbursementAmt_ProviderAvg'] = pdfFeatEng.groupby(['Provider'])['OPAnnualReimbursementAmt'].transform('mean')
133
+ pdfFeatEng['OPAnnualDeductibleAmt_ProviderAvg'] = pdfFeatEng.groupby(['Provider'])['OPAnnualDeductibleAmt'].transform('mean')
134
+ return pdfFeatEng
135
+
136
+
137
+ def fit(pdfScaled):
138
+ #--- determine the centroids of the kmeans clusters
139
+ #--- refit kmeans clustering according to the pre-scaled data provided
140
+ #--- note: this all assumes that the nature of the data and the number of clusters remain unchanged
141
+ m_klngNumClusters = 3
142
+ if (m_blnTraceOn): print("TRACE (" + m_kstrFile + ".fit) instantiate KMeans ...")
143
+ mdlKMeans = KMeans(n_clusters=m_klngNumClusters, max_iter=50, random_state=2022) #--- #clusters was learned from training
144
+
145
+ if (m_blnTraceOn): print("TRACE (" + m_kstrFile + ".fit) fitting data (scaled) ...")
146
+ mdlKMeans.fit(pdfScaled) #--- fit on test/prod data
147
+
148
+ return mdlKMeans #--- this ibject will give us all results based on kmeans
149
+
150
+
151
+ def train(pdfTrainData):
152
+ mdlAnoms = KMeans(n_clusters=3, max_iter=50, random_state=2022)
153
+ mdlAnoms.fit(pdfTrainData.values)
154
+ save_kmeansToPkl(mdlAnoms)
155
+ return mdlAnoms
lib/models/mdl_logR.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sklearn.linear_model import LogisticRegressionCV
2
+ import lib.utils as libPaths
3
+ import pickle
4
+
5
+
6
+ m_kstrFile = __file__
7
+ m_kstrDataPath = libPaths.pth_data
8
+ m_kstrBinModelPath = libPaths.pth_binModels
9
+ m_kstrModelPath = m_kstrBinModelPath + 'lgr_model_colab.pkl'
10
+
11
+
12
+ #--- Supervised: Logistic Regession
13
+ def load_fromPkl():
14
+ with open(m_kstrModelPath, 'rb') as filPkl:
15
+ mdlAnoms = pickle.load(filPkl)
16
+ return mdlAnoms
17
+
18
+
19
+
20
+ def save_toPkl(mdlAnoms):
21
+ with open(m_kstrModelPath, 'wb') as filPkl:
22
+ pickle.dump(mdlAnoms, filPkl)
23
+ return mdlAnoms
24
+
25
+
26
+
27
+ def predict(npaData):
28
+ #--- input: numpy.ndarray of feature eng, and scaled data
29
+ mdlAnoms = load_fromPkl()
30
+ npaPredict = mdlAnoms.predict(npaData)
31
+
32
+ print("INFO (npaPredict.shape): ", npaPredict.shape)
33
+ return npaPredict
34
+
35
+
36
+
37
+ def train(pdfTrainData):
38
+ mdlAnoms = LogisticRegressionCV()
39
+ mdlAnoms.fit(pdfTrainData.values)
40
+ save_toPkl(mdlAnoms)
41
+ return mdlAnoms
lib/models/mdl_svm.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sklearn.svm import LinearSVC
2
+ import lib.utils as libPaths
3
+ import pickle
4
+
5
+
6
+ m_kstrFile = __file__
7
+ m_kstrDataPath = libPaths.pth_data
8
+ m_kstrBinModelPath = libPaths.pth_binModels
9
+ m_kstrModelPath = m_kstrBinModelPath + 'svm_model_colab.pkl'
10
+
11
+
12
+ #--- Supervised: Support Vector Machines
13
+ def load_fromPkl():
14
+ with open(m_kstrModelPath, 'rb') as filPkl:
15
+ mdlAnoms = pickle.load(filPkl)
16
+ return mdlAnoms
17
+
18
+
19
+
20
+ def save_toPkl(mdlAnoms):
21
+ with open(m_kstrModelPath, 'wb') as filPkl:
22
+ pickle.dump(mdlAnoms, filPkl)
23
+ return mdlAnoms
24
+
25
+
26
+
27
+ def predict(npaData):
28
+ #--- input: numpy.ndarray of feature eng, and scaled data
29
+ mdlAnoms = load_fromPkl()
30
+ npaPredict = mdlAnoms.predict(npaData)
31
+ print("INFO (" + m_kstrFile + ".predict) npaPredict.shape: ", npaPredict.shape)
32
+ return npaPredict
33
+
34
+
35
+
36
+ def train(pdfTrainData):
37
+ mdlAnoms = LinearSVC()
38
+ mdlAnoms.fit(pdfTrainData.values)
39
+ save_toPkl(mdlAnoms)
40
+ return mdlAnoms
lib/models/mdl_utils.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import pickle
3
+ import lib.utils as libPaths
4
+
5
+ m_blnTraceOn = False
6
+
7
+ #--- load, merge data from file
8
+ m_kstrDataPath = libPaths.pth_data
9
+ m_kstrModelPath = libPaths.pth_model
10
+ m_kstrBinModelPath = libPaths.pth_binModels
11
+
12
+ #m_kstrScalerPath_claims = m_kstrBinModelPath + 'stdClaims_scaler_colab.pkl' #--- does not work for scaling claims data; from v1.0.2; using 1.1.1
13
+ #m_kstrScalerPath_claims2 = m_kstrBinModelPath + 'std_scaler_unsuperv_colab.pkl' #--- does not work; expects 32 features
14
+ #m_kstrScalerPath_claims = m_kstrBinModelPath + 'stdClaims_scaler_colab_v1.2.1.pkl'
15
+ m_kstrScalerPath_claims111 = m_kstrBinModelPath + 'claims_stdScaler_v1.1.1_27cols.pkl'
16
+ m_kstrScalerPath_claims121 = m_kstrBinModelPath + 'claims_stdScaler_v1.2.1_27cols.pkl'
17
+ m_kstrScalerPath_claims_py3816_sk111hp = m_kstrBinModelPath + 'claims_stdScl_py3816_sk111hp_27cols.pkl'
18
+ m_kstrScalerPath_claims = m_kstrScalerPath_claims_py3816_sk111hp
19
+
20
+ m_kstrScalerPath_providers111 = m_kstrBinModelPath + 'prov_stdScaler_v1.1.1_32cols.pkl'
21
+ m_kstrScalerPath_providers121 = m_kstrBinModelPath + 'prov_stdScaler_v1.2.1_32cols.pkl'
22
+ m_kstrScalerPath_prov_py3816_sk111 = m_kstrBinModelPath + 'prov_stdScl_py3816_sk111_32cols.pkl'
23
+ m_kstrScalerPath_prov_py3816_sk111hp = m_kstrBinModelPath + 'prov_stdScl_py3816_sk111hp_32cols.pkl'
24
+ m_kstrScalerPath_prov = m_kstrScalerPath_prov_py3816_sk111hp
25
+
26
+ m_kstrScalerPath_providers_superv = m_kstrBinModelPath + 'gbc_scaler.pkl'
27
+ m_kstrScalerPath_providers_train = m_kstrBinModelPath + "stdProvider_scaler.pkl"
28
+
29
+
30
+
31
+ def doProviders_stdScaler(pdfFeatEng, blnIsTrain=False, hasGroupByProviderCols=True):
32
+ print("INFO (claims.do_stdScaler): blnIsTrain, ", blnIsTrain)
33
+
34
+ #--- Note: prediction runs on X_val
35
+ '''
36
+ #--- WARN: The default value of numeric_only in DataFrameGroupBy.sum is deprecated.
37
+ # In a future version, numeric_only will default to False. Either specify
38
+ # numeric_only or select only columns which should be valid for the function.
39
+ '''
40
+
41
+ #--- WARN: this code groups all data by provider; any predictions will also be by provider
42
+ pdfGroupBy = pdfFeatEng
43
+ if (hasGroupByProviderCols):
44
+ pdfGroupBy = pdfFeatEng.groupby(['Provider'], as_index=False).agg('sum')
45
+
46
+ X = pdfGroupBy
47
+
48
+ try:
49
+ X = X.drop(columns=['Provider'], axis=1) #--- cannot scale; text
50
+ except KeyError:
51
+ #--- likely column not found; invalid fxn call
52
+ print("ERROR (mdlUtils.doProviders_stdScaler): Provider col not found")
53
+
54
+ try:
55
+ X = X.drop(columns=['PotentialFraud'], axis=1)
56
+ except KeyError:
57
+ #--- likely column not found; invalid fxn call
58
+ if (blnIsTrain): print("ERROR (mdlUtils.doProviders_stdScaler): Potential Fraud col not found")
59
+
60
+
61
+ #--- apply std scaler
62
+ #--- WARN: scaling is also grouped by provider
63
+ if (m_blnTraceOn): print("INFO (mdlUtils.doProviders_stdScaler) cols: ", X.columns) #--- 32cols
64
+ X_std = fitProviders_txfStdScaler(X, blnIsTrain)
65
+ return X_std
66
+
67
+
68
+
69
+ def doClaims_stdScaler(pdfFeatEng, blnIsTrain=False):
70
+ print("INFO (mdlUtils.doClaims_stdScaler): blnIsTrain, ", blnIsTrain)
71
+
72
+ #--- Note: prediction runs on X_val
73
+ '''
74
+ #--- WARN: The default value of numeric_only in DataFrameGroupBy.sum is deprecated.
75
+ # In a future version, numeric_only will default to False. Either specify
76
+ # numeric_only or select only columns which should be valid for the function.
77
+ '''
78
+
79
+ #--- WARN: this code groups all data by provider; any predictions will also be by provider
80
+ X = pdfFeatEng
81
+
82
+ try:
83
+ X = X.drop(columns=['Provider'], axis=1) #--- cannot scale; text
84
+ except KeyError:
85
+ #--- likely column not found; invalid fxn call
86
+ print("ERROR (mdlUtils.do_stdScaler): Provider col not found")
87
+
88
+ try:
89
+ X = X.drop(columns=['PotentialFraud'], axis=1)
90
+ except KeyError:
91
+ #--- likely column not found; invalid fxn call
92
+ if (blnIsTrain): print("ERROR (mdlUtils.do_stdScaler): Potential Fraud col not found")
93
+
94
+
95
+ #--- apply std scaler
96
+ #--- WARN: scaling is also grouped by provider
97
+ #print("INFO (mdlUtils.doClaims_stdScaler) cols: ", X.columns)
98
+ X_std = fitClaims_txfStdScaler(X, blnIsTrain)
99
+ return X_std
100
+
101
+
102
+
103
+ def doProviders_stdScaler_toPdf(npaScaled):
104
+ #--- NOTE: the list of cols came from doProvider_stdScaler; print(X.columns)
105
+ aryCols = ['InscClaimAmtReimbursed', 'DeductibleAmtPaid', 'AdmittedDays',
106
+ 'NoOfMonths_PartACov', 'NoOfMonths_PartBCov', 'ChronicCond_Alzheimer',
107
+ 'ChronicCond_Heartfailure', 'ChronicCond_KidneyDisease',
108
+ 'ChronicCond_Cancer', 'ChronicCond_ObstrPulmonary',
109
+ 'ChronicCond_Depression', 'ChronicCond_Diabetes',
110
+ 'ChronicCond_IschemicHeart', 'ChronicCond_Osteoporasis',
111
+ 'ChronicCond_rheumatoidarthritis', 'ChronicCond_stroke',
112
+ 'IPAnnualReimbursementAmt', 'IPAnnualDeductibleAmt',
113
+ 'OPAnnualReimbursementAmt', 'OPAnnualDeductibleAmt', 'Age', 'DeadOrNot',
114
+ 'Gender_2', 'Race_2', 'Race_3', 'Race_5',
115
+ 'ClaimReimbursement_ProviderAvg',
116
+ 'ClaimReimbursement_AttendingPhysician',
117
+ 'ClaimReimbursement_OperatingPhysician',
118
+ 'DeductibleAmtPaid_ProviderAvg', 'DeductibleAmtPaid_AttendingPhysician',
119
+ 'DeductibleAmtPaid_OperatingPhysician']
120
+
121
+ #npaScaled = do_stdScaler(pdfFeatEng)
122
+ pdfScaled = pd.DataFrame(npaScaled, columns=aryCols)
123
+ return pdfScaled
124
+
125
+
126
+
127
+ def doClaims_stdScaler_toPdf(npaScaled):
128
+ #--- NOTE: the list of cols came from doClaims_stdScaler; print(X.columns)
129
+ aryCols = ['InscClaimAmtReimbursed', 'DeductibleAmtPaid', 'AdmittedDays',
130
+ 'RenalDiseaseIndicator', 'NoOfMonths_PartACov', 'NoOfMonths_PartBCov', 'ChronicCond_Alzheimer',
131
+ 'ChronicCond_Heartfailure', 'ChronicCond_KidneyDisease',
132
+ 'ChronicCond_Cancer', 'ChronicCond_ObstrPulmonary',
133
+ 'ChronicCond_Depression', 'ChronicCond_Diabetes',
134
+ 'ChronicCond_IschemicHeart', 'ChronicCond_Osteoporasis',
135
+ 'ChronicCond_rheumatoidarthritis', 'ChronicCond_stroke',
136
+ 'IPAnnualReimbursementAmt', 'IPAnnualDeductibleAmt',
137
+ 'OPAnnualReimbursementAmt', 'OPAnnualDeductibleAmt', 'Age', 'DeadOrNot',
138
+ 'Gender_2', 'Race_2', 'Race_3', 'Race_5']
139
+
140
+ #npaScaled = do_stdScaler(pdfFeatEng)
141
+ pdfScaled = pd.DataFrame(npaScaled, columns=aryCols)
142
+ return pdfScaled
143
+
144
+
145
+
146
+
147
+ def fitClaims_stdScaler(pdfData, blnIsTrain=False):
148
+ #--- apply scaler
149
+ #--- WARN: scaling is not grouped by provider
150
+ from sklearn.preprocessing import StandardScaler
151
+
152
+ #--- note: this is a numpy.ndarray
153
+ #--- we need to fit the scaler, and then save as a pkl file
154
+ #strScalerPath = m_kstrScalerPath_claims
155
+ strScalerPath = m_kstrScalerPath_claims
156
+ # strScalerPath = m_kstrBinModelPath + "stdClaims_scaler_colab.pkl"
157
+ if (m_blnTraceOn): print("INFO (lib.model.fitClaims_stdScalar): ", strScalerPath)
158
+ if (blnIsTrain):
159
+ scaler = StandardScaler()
160
+ sclFit = scaler.fit(pdfData)
161
+ #--- if we train locally; write out to gbc_scalar.pkl
162
+ #--- we do not want to overwrite the colab version used for test
163
+ strScalerPath = m_kstrBinModelPath + "stdClaims_scaler.pkl"
164
+ if (m_blnTraceOn): print("INFO (lib.model.fit_stdScalar) Using local pkl for Train: ", strScalerPath)
165
+ with open(strScalerPath, 'wb') as filPkl:
166
+ pickle.dump(sclFit, filPkl)
167
+ else:
168
+ #--- we need to load the pkl file
169
+ import sklearn
170
+ if (m_blnTraceOn): print("INFO (lib.model.fit_stdScalar) Using colab pkl for Test: ", strScalerPath)
171
+ with open(strScalerPath, 'rb') as filPkl:
172
+ sclFit = pickle.load(filPkl)
173
+ if (m_blnTraceOn): print("TRACE (libModel.fitClaims_stdScalar) sclFit.type: ", type(sclFit))
174
+
175
+ #--- testing
176
+ scaler = StandardScaler()
177
+ if (m_blnTraceOn): print("TRACE (libModel.fitClaims_stdScalar) StdScaler.version: ", scaler.__getstate__()['_sklearn_version'])
178
+ if (m_blnTraceOn): print("TRACE (libModel.fitClaims_stdScalar) sclFit.version: " , sclFit.__getstate__()['_sklearn_version'])
179
+ if (m_blnTraceOn): print("TRACE (libModel.fitClaims_stdScalar) sklearn.version: " , sklearn.__version__)
180
+ return sclFit
181
+
182
+
183
+
184
+ def fitProviders_stdScaler(pdfData, blnIsTrain=False):
185
+ #--- apply scaler
186
+ #--- WARN: scaling is also grouped by provider
187
+ from sklearn.preprocessing import StandardScaler
188
+
189
+ #--- note: this is a numpy.ndarray
190
+ #--- we need to fit the scaler, and then save as a pkl file
191
+ #strScalerPath = m_kstrScalerPath_providers
192
+ #strScalerPath = m_kstrScalerPath_providers_train
193
+ strScalerPath = m_kstrScalerPath_prov
194
+ print("INFO (libModel.fitProviders_stdScalar): ", strScalerPath)
195
+ if (blnIsTrain):
196
+ scaler = StandardScaler()
197
+ sclFit = scaler.fit(pdfData)
198
+ #--- if we train locally; write out to gbc_scalar.pkl
199
+ #--- we do not want to overwrite the colab version used for test
200
+ strScalerPath = m_kstrScalerPath_providers_train #--- works for provider training
201
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar) Using local pkl for Train: ", strScalerPath)
202
+ with open(strScalerPath, 'wb') as filPkl:
203
+ pickle.dump(sclFit, filPkl)
204
+ else:
205
+ #--- we need to load the pkl file
206
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar) Using colab pkl for Test: ", strScalerPath)
207
+ with open(strScalerPath, 'rb') as filPkl:
208
+ sclFit = pickle.load(filPkl)
209
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar) sclFit.type: ", type(sclFit))
210
+ return sclFit
211
+
212
+
213
+
214
+ def fitProviders_stdScalerSuperv(pdfData, blnIsTrain=False):
215
+ #--- apply scaler
216
+ #--- WARN: scaling is also grouped by provider
217
+ from sklearn.preprocessing import StandardScaler
218
+
219
+ #--- note: this is a numpy.ndarray
220
+ #--- we need to fit the scaler, and then save as a pkl file
221
+ strScalerPath = m_kstrScalerPath_prov
222
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar): ", strScalerPath)
223
+ if (blnIsTrain):
224
+ scaler = StandardScaler()
225
+ sclFit = scaler.fit(pdfData)
226
+ #--- if we train locally; write out to gbc_scalar.pkl
227
+ #--- we do not want to overwrite the colab version used for test
228
+ strScalerPath = m_kstrBinModelPath + "stdProvider_scaler.pkl"
229
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar) Using local pkl for Train: ", strScalerPath)
230
+ with open(strScalerPath, 'wb') as filPkl:
231
+ pickle.dump(sclFit, filPkl)
232
+ else:
233
+ #--- we need to load the pkl file
234
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar) Using colab pkl for Test: ", strScalerPath)
235
+ with open(strScalerPath, 'rb') as filPkl:
236
+ sclFit = pickle.load(filPkl)
237
+ if (m_blnTraceOn): print("TRACE (libModel.fitProviders_stdScalar) sclFit.type: ", type(sclFit))
238
+ return sclFit
239
+
240
+
241
+
242
+ def fitProviders_txfStdScaler(pdfData, blnIsTrain=False):
243
+ from sklearn.preprocessing import StandardScaler
244
+ sclFit = fitProviders_stdScaler(pdfData, blnIsTrain)
245
+ X_std = sclFit.transform(pdfData)
246
+ return X_std
247
+
248
+
249
+
250
+ def fitClaims_txfStdScaler(pdfData, blnIsTrain=False):
251
+ from sklearn.preprocessing import StandardScaler
252
+ sclFit = fitClaims_stdScaler(pdfData, blnIsTrain)
253
+
254
+
255
+ X_std = sclFit.transform(pdfData)
256
+ return X_std
lib/models/mdl_xgb.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from sklearn.ensemble import GradientBoostingClassifier
3
+ import lib.utils as libPaths
4
+ import pickle
5
+ import sys
6
+
7
+
8
+ m_kstrFile = __file__
9
+ m_kstrDataPath = libPaths.pth_data
10
+ m_kstrBinModelPath = libPaths.pth_binModels
11
+ m_kstrModelPath_gbc = m_kstrBinModelPath + 'gbc_model_colab.pkl'
12
+ m_kstrModelPath_prov111 = m_kstrBinModelPath + 'prov_gbc_v1.1.1_32cols.pkl' #--- ERROR: __randomstate_ctor() takes from 0 to 1 positional arguments but 2 were given
13
+ m_kstrModelPath_prov121 = m_kstrBinModelPath + 'prov_gbc_v1.2.1_32cols.pkl'
14
+ m_kstrModelPath_prov_py3816_sk111hp = m_kstrBinModelPath + 'prov_gbc_py3816_sk111hp_32cols.pkl'
15
+ m_kstrModelPath = m_kstrModelPath_prov_py3816_sk111hp
16
+
17
+ m_blnTraceOn = True
18
+
19
+
20
+
21
+ #--- Supervised: xg boost; gradient boosting classifier
22
+ def load_fromPkl():
23
+ try:
24
+ with open(m_kstrModelPath, 'rb') as filPkl:
25
+ mdlAnoms = pickle.load(filPkl)
26
+ return mdlAnoms
27
+
28
+ except:
29
+ e = sys.exc_info()
30
+ print("ERROR (mdl_xgb.load_fromPkl_genError): ", e)
31
+
32
+
33
+
34
+ def save_toPkl(mdlAnoms):
35
+ with open(m_kstrModelPath, 'wb') as filPkl:
36
+ pickle.dump(mdlAnoms, filPkl)
37
+ return mdlAnoms
38
+
39
+
40
+
41
+ def predict(npaData):
42
+
43
+ try:
44
+ #--- input: numpy.ndarray of feature eng, and scaled data
45
+ mdlAnoms = load_fromPkl()
46
+ if (m_blnTraceOn): print("TRACE (mdl_xgb.predict): data loaded ... ")
47
+ npaPredict = mdlAnoms.predict(npaData)
48
+
49
+ except:
50
+ e = sys.exc_info()
51
+ print("ERROR (mdl_xgb.predict_genError1): ", e)
52
+
53
+
54
+ #--- AttributeError: 'GradientBoostingClassifier' object has no attribute '_loss'
55
+ #--- version of scikit-learn? Monika: ?.?.? ; Iain: 1.2.0
56
+
57
+ #print("INFO (type.npaPredict): ", type(npaPredict))
58
+ #if (m_blnTraceOn): print("TRACE (mdl_xgb.predict) npaPredict.shape: ", npaPredict.shape)
59
+ return npaPredict
60
+
61
+
62
+ def train(pdfTrainData):
63
+ mdlAnoms = GradientBoostingClassifier()
64
+ mdlAnoms.fit(pdfTrainData.values)
65
+ save_toPkl(mdlAnoms)
66
+ return mdlAnoms
lib/utils.py CHANGED
@@ -25,6 +25,7 @@ pth_dtaApp = pth_data #--- working folders for
25
  pth_dtaDemoTiles = pth_data + "demo_tiles/" #--- dedicated area for demo data
26
  pth_dtaTiles = pth_data + "tiles/"
27
  pth_dtaWsi = pth_data + "wsi/"
 
28
 
29
  #--- lib paths
30
  pth_libModels = pth_lib + "models/"
 
25
  pth_dtaDemoTiles = pth_data + "demo_tiles/" #--- dedicated area for demo data
26
  pth_dtaTiles = pth_data + "tiles/"
27
  pth_dtaWsi = pth_data + "wsi/"
28
+ pth_dtaTileSamples = pth_dtaDemoTiles + "raw/sample/"
29
 
30
  #--- lib paths
31
  pth_libModels = pth_lib + "models/"
util_dockerPreRun.sh β†’ scripts/docker/util_docker_preRun.sh RENAMED
@@ -1,10 +1,10 @@
1
  #!/bin/bash
2
 
3
  #--- Note: this file is designed to run locally as well as within docker to prep the environment
 
 
 
4
  #--- for volume initialization; ensure folders are in place; assume: we are in the /app folder
5
- mkdir -p data/demo_tiles/raw
6
- mkdir -p data/tiles/raw data/tiles/pred data/tiles/grad_bg data/tiles/grad_wt data/tiles/grad_vt
7
- mkdir -p data/wsi/raw
8
 
9
 
10
  <<blockComment
@@ -12,9 +12,21 @@ mkdir -p data/wsi/raw
12
  - this is done to ensure that the model can be stored within gitHub
13
  - the split model is recreated on docker container startup using the cat command
14
  blockComment
 
 
 
 
 
 
 
 
 
15
 
16
  #--- recreate single model file from its parts, stored within a specific model version folder
17
- ./bin/models/util_joinModel.sh './bin/models/deeplabv3*vhflip30/model_a*' ./bin/models/model.pth
 
 
 
18
 
19
  #--- run streamlit/fastapi
20
- ./util_startLocal_streamlitFastApi.sh
 
1
  #!/bin/bash
2
 
3
  #--- Note: this file is designed to run locally as well as within docker to prep the environment
4
+ #--- Entry: this script is assumed to run from the /app root folder
5
+ #--- Usage: ./scripts/docker/util_docker_preRun.sh
6
+
7
  #--- for volume initialization; ensure folders are in place; assume: we are in the /app folder
 
 
 
8
 
9
 
10
  <<blockComment
 
12
  - this is done to ensure that the model can be stored within gitHub
13
  - the split model is recreated on docker container startup using the cat command
14
  blockComment
15
+ echo -e "INFO(util_docker_preRun):\t Initializing ..."
16
+
17
+ strpth_pwd=$(pwd)
18
+ strpth_scriptLoc=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
19
+ strpth_scrHome="${strpth_scriptLoc}/../"
20
+ strpth_appHome="${strpth_scrHome}../"
21
+ strpth_scrModels="${strpth_scrHome}models/"
22
+
23
+ echo "strpth_appHome = ${strpth_appHome}"
24
 
25
  #--- recreate single model file from its parts, stored within a specific model version folder
26
+ strpth_binModels="${strpth_appHome}bin/models/"
27
+ echo "strpth_binModels = ${strpth_binModels}"
28
+ #$("'${strpth_scrModels}util_joinModel.sh' '${strpth_binModels}deeplabv3*vhflip30/model_a*' '${strpth_binModels}model.pth'")
29
+ eval "'${strpth_scrModels}/util_joinModel.sh' '${strpth_binModels}/deeplabv3*vhflip30/model_a*' '${strpth_binModels}/model.pth'"
30
 
31
  #--- run streamlit/fastapi
32
+ eval "'${strpth_scrHome}/streamlitFastApi/util_local_runStreamlitFastApi.sh'"
scripts/docker/util_local_buildDockerDemo.sh ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ #--- Note: this file is designed to run locally to build the docker image
4
+ #--- Entry: this script is assumed to run from the /app root folder
5
+ #--- Usage: ./scripts/docker/util_local_buildDockerDemo.sh
6
+ #--- Assume: any associated containers are not running
7
+
8
+ <<blockComment
9
+ util_local_buildDockerDemo -> img_stm_omdenasaudi_hcc:demo -> ctr_stm_omdenasaudi_hcc:demo
10
+ blockComment
11
+
12
+
13
+ #--- initialize/configuration
14
+ echo "TRACE: Initializing ..."
15
+ kstr_defDkrHubId="kidcoconut73"
16
+ kstr_defDkrImageName="img_stm_omdenasaudi_hcc"
17
+ kstr_defDkrTagVersion="0.1.2"
18
+ kstr_defDkrTagStage="demo"
19
+
20
+ strpth_pwd=$(pwd)
21
+ strpth_scriptLoc=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
22
+ strpth_scrHome="${strpth_scriptLoc}/../"
23
+ strpth_appHome="${strpth_scrHome}/../"
24
+
25
+ #--- declarations
26
+ echo "TRACE: Declarations ..."
27
+
28
+ #strUtl_scriptLoc="$(utl_getScriptLoc)"
29
+ source ${strpth_scrHome}/util.sh
30
+
31
+ #kstr_dkrImg="kidcoconut73/img_stm_omdenasaudi_hcc:demo"
32
+ #kstr_dkrCtr="kidcoconut73/ctr_stm_omdenasaudi_hcc:demo"
33
+ kstr_dkrHubImg="${kstr_defDkrHubId}/${kstr_defDkrImageName}:${kstr_defDkrTagStage}"
34
+ kstr_dkrImg="${kstr_defDkrImageName}:${kstr_defDkrTagVersion}"
35
+ kstr_dkrCtr="${kstr_dkrImg/img_/ctr_}" #--- bash replace one occurrence
36
+
37
+
38
+
39
+ function utl_trace_config {
40
+ #echo ""
41
+ local kbln_enableLog=true
42
+ utl_logInfo $kbln_enableLog 0 "(utl_trace_config) ... echo configuration"
43
+
44
+ utl_trace_var "strpth_pwd" $strpth_pwd
45
+ utl_trace_var "strpth_scriptLoc" $strpth_scriptLoc
46
+ echo ""
47
+ utl_trace_var "kstr_defDkrHubId" $kstr_defDkrHubId
48
+ utl_trace_var "kstr_defDkrImageName" $kstr_defDkrImageName
49
+ utl_trace_var "kstr_defDkrTagVersion" $kstr_defDkrTagVersion
50
+ utl_trace_var "kstr_defDkrTagStage" $kstr_defDkrTagStage
51
+ echo ""
52
+ utl_trace_var "kstr_dkrHubImg" $kstr_dkrHubImg
53
+ utl_trace_var "kstr_dkrImg" $kstr_dkrImg
54
+ utl_trace_var "kstr_dkrCtr" $kstr_dkrCtr
55
+ echo ""
56
+ }
57
+
58
+ #echo -e "\nTRACE: Echo config ..."
59
+ utl_trace_config
60
+
61
+
62
+ #--- to build/rebuild the image; make sure you stop and remove the container if you are replacing/upgrading; or change the version tag# from 0.1
63
+ #--- stop the container if it is running
64
+ #--- delete container if it exists
65
+ echo -e "\nTRACE: Stop and remove container if it exists ..."
66
+ docker stop $kstr_dkrCtr
67
+ docker rm $kstr_dkrCtr
68
+
69
+ #--- build the docker image
70
+ echo -e "\nTRACE: Build the docker image ..."
71
+ docker build -t $kstr_dkrImg .
72
+
73
+
74
+ #--- to tag the image prior to push to DockerHub; docker login and then register user/image:tag
75
+ #--- to push this image to DockerHub, example based on the repo: kidcoconut73/img_stm_omdenasaudi_hcc
76
+ # docker tag img_omdenasaudi_hcc:0.1 kidcoconut73/img_stm_omdenasaudi_hcc:demo
77
+ # docker tag img_omdenasaudi_hcc:0.1 kidcoconut73/img_stm_omdenasaudi_hcc:0.1
78
+ #--- tag the image
79
+ echo -e "\nTRACE: Tag the image ..."
80
+ docker tag ${kstr_dkrImg} $kstr_dkrHubImg
81
+ docker tag ${kstr_dkrImg} "${kstr_defDkrHubId}/${kstr_defDkrImageName}:${kstr_defDkrTagVersion}"
82
+
83
+
84
+ #--- push the image to dockerHub
85
+ docker push kidcoconut73/img_stm_omdenasaudi_hcc:demo
scripts/docker/util_local_runDockerDemo.sh ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ #--- Note: this file is designed to run locally to launch docker
4
+ #--- Entry: this script is assumed to run from the /app root folder
5
+ #--- Usage: ./scripts/util_local_runDockerDemo.sh
6
+ #--- Assume: docker image has been built; container is not running
7
+
8
+ <<blockComment
9
+ util_local_runDockerDemo -> Dockerfile -> util_dockerPreRun -> util_local_runStreamlitFastApi
10
+ blockComment
11
+
12
+
13
+ #--- initialize/config
14
+ kstr_defDkrHubId="kidcoconut73"
15
+ kstr_defDkrImageName="img_stm_omdenasaudi_hcc"
16
+ kstr_defDkrCtrName=${kstr_defDkrImageName/img_/ctr_}
17
+ kstr_defDkrTagVersion="0.1.2"
18
+ kstr_defDkrTagStage="demo"
19
+
20
+ kstr_dkrImg="${kstr_defDkrImageName}:${kstr_defDkrTagVersion}"
21
+ kstr_dkrCtr="${kstr_defDkrImageName/img_/ctr_}" #--- bash replace one occurrence
22
+
23
+ #--- stop the container if it is running
24
+ docker stop $kstr_dkrCtr
25
+
26
+ #--- delete container if it exists
27
+ docker rm $kstr_dkrCtr
28
+
29
+ #--- to run the container from the image; specific port mapping (-p) vs any available port mapping (-P)
30
+ # docker run -p 49400:39400 -p 49500:39500 --name ctr_stmOmdenaSaudiHcc -v ./data:/app/data img_stm_omdenasaudi_hcc:0.1
31
+
32
+ #--- run docker demo locally
33
+ docker run -p 49400:39400 -p 49500:39500 --name $kstr_dkrCtr -v ./data:/app/data $kstr_dkrImg
scripts/huggingface/util_local_readyDeploy_toHugSpace_streamlit.sh ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ #--- Note: this file is designed to run locally to ready the deploy branch for hugspace
4
+ #--- Entry: this script is assumed to run from the /app root folder
5
+ #--- Usage: ./scripts/util_local_readyDeploy_toHugSpace_streamlit.sh
6
+
7
+ <<blockComment
8
+ bash: util_local_readyDeploy_toHugSpace_streamlit -> git
9
+ git: local/task-5-deployment -> omdena/deploy_hugspace_streamlit -> hugspace/main
10
+ blockComment
11
+
12
+
13
+ #--- initialize/configuration
14
+ echo "TRACE: Initializing ..."
15
+ kstr_hugspaceId="kidcoconut"
16
+
17
+
18
+ #--- git checkout deploy_hugspace_streamlit
19
+ #--- git merge task-5-deployment
20
+ #--- delete all unnecessary files
21
+ <<deadCode
22
+ kstr_defDkrHubId="kidcoconut73"
23
+ kstr_defDkrImageName="img_stm_omdenasaudi_hcc"
24
+ kstr_defDkrTagVersion="0.1.2"
25
+ kstr_defDkrTagStage="demo"
26
+ strpth_pwd=$(pwd)
27
+ strpth_scriptLoc=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
28
+
29
+
30
+ #--- declarations
31
+ echo "TRACE: Declarations ..."
32
+
33
+ #strUtl_scriptLoc="$(utl_getScriptLoc)"
34
+ source ${strpth_scriptLoc}/util.sh
35
+
36
+ #kstr_dkrImg="kidcoconut73/img_stm_omdenasaudi_hcc:demo"
37
+ #kstr_dkrCtr="kidcoconut73/ctr_stm_omdenasaudi_hcc:demo"
38
+ kstr_dkrHubImg="${kstr_defDkrHubId}/${kstr_defDkrImageName}:${kstr_defDkrTagStage}"
39
+ kstr_dkrImg="${kstr_defDkrImageName}:${kstr_defDkrTagVersion}"
40
+ kstr_dkrCtr="${kstr_dkrImg/img_/ctr_}" #--- bash replace one occurrence
41
+
42
+
43
+
44
+ function utl_trace_config () {
45
+ echo ""
46
+ utl_trace_var "strpth_pwd" $strpth_pwd
47
+ utl_trace_var "strpth_scriptLoc" $strpth_scriptLoc
48
+ echo ""
49
+ utl_trace_var "kstr_defDkrHubId" $kstr_defDkrHubId
50
+ utl_trace_var "kstr_defDkrImageName" $kstr_defDkrImageName
51
+ utl_trace_var "kstr_defDkrTagVersion" $kstr_defDkrTagVersion
52
+ utl_trace_var "kstr_defDkrTagStage" $kstr_defDkrTagStage
53
+ echo ""
54
+ utl_trace_var "kstr_dkrHubImg" $kstr_dkrHubImg
55
+ utl_trace_var "kstr_dkrImg" $kstr_dkrImg
56
+ utl_trace_var "kstr_dkrCtr" $kstr_dkrCtr
57
+ echo ""
58
+ }
59
+
60
+ echo -e "\nTRACE: Echo config ...\n"
61
+ utl_trace_config
62
+
63
+
64
+ #--- to build/rebuild the image; make sure you stop and remove the container if you are replacing/upgrading; or change the version tag# from 0.1
65
+ #--- stop the container if it is running
66
+ #--- delete container if it exists
67
+ echo -e "\nTRACE: Stop and remove container if it exists ..."
68
+ docker stop $kstr_dkrCtr
69
+ docker rm $kstr_dkrCtr
70
+
71
+ #--- build the docker image
72
+ echo -e "\nTRACE: Build the docker image ..."
73
+ docker build -t $kstr_dkrImg .
74
+
75
+
76
+ #--- to tag the image prior to push to DockerHub; docker login and then register user/image:tag
77
+ #--- to push this image to DockerHub, example based on the repo: kidcoconut73/img_stm_omdenasaudi_hcc
78
+ # docker tag img_omdenasaudi_hcc:0.1 kidcoconut73/img_stm_omdenasaudi_hcc:demo
79
+ # docker tag img_omdenasaudi_hcc:0.1 kidcoconut73/img_stm_omdenasaudi_hcc:0.1
80
+ #--- tag the image
81
+ echo -e "\nTRACE: Tag the image ..."
82
+ docker tag ${kstr_dkrImg} $kstr_dkrHubImg
83
+ docker tag ${kstr_dkrImg} "${kstr_defDkrHubId}/${kstr_defDkrImageName}:${kstr_defDkrTagVersion}"
84
+
85
+
86
+ #--- push the image to dockerHub
87
+ # docker push kidcoconut73/img_stm_omdenasaudi_hcc:demo
88
+ deadCode
{bin β†’ scripts}/models/util_joinModel.sh RENAMED
@@ -13,14 +13,25 @@ blkHeader
13
  #none
14
 
15
 
16
- #--- initialization
17
  #--- $1: first arg; source pattern match; eg './bin/models/deeplabv3*vhflip30/model_a*'; Note that this is wildcarded so must be in quotes
18
  #--- $n: last arg; dest model file; eg. ./bin/models/model.pth
 
19
  strPth_patternMatch=$1
 
 
 
 
 
20
  strPth_filMatch=( $strPth_patternMatch ) #--- expand the pattern match; get the first value of the pattern match
21
  strPth_parentFld=$(dirname $strPth_filMatch) #--- get the parent dir of the first file match
22
  strPth_mdlFile=${@: -1} #--- Note: this gets the last arg; otherwise the 2nd arg would be an iteration of the 1st arg wildcard
23
 
 
 
 
 
 
24
  #echo "TRACE: strPth_patternMatch= $strPth_patternMatch"
25
  #echo "TRACE: strPth_filMatch= $strPth_filMatch"
26
  #echo "TRACE: strPth_parentFld= $strPth_parentFld"
@@ -29,4 +40,6 @@ strPth_mdlFile=${@: -1} #--- Note: this gets the last a
29
  #--- reconstitute model
30
  #--- Note: cat command does not work with single-quote literals; do not reapply single quotes
31
  #echo "cat ${strPth_patternMatch} > ${strPth_mdlFile}"
 
32
  cat ${strPth_patternMatch} > ${strPth_mdlFile}
 
 
13
  #none
14
 
15
 
16
+ #--- initialize/configuration
17
  #--- $1: first arg; source pattern match; eg './bin/models/deeplabv3*vhflip30/model_a*'; Note that this is wildcarded so must be in quotes
18
  #--- $n: last arg; dest model file; eg. ./bin/models/model.pth
19
+ echo -e "INFO(util_joinModel):\t Initializing ..."
20
  strPth_patternMatch=$1
21
+ if [ -z "$strPth_patternMatch" ]; then
22
+ echo "WARN: no args provided. Exiting script."
23
+ exit
24
+ fi
25
+
26
  strPth_filMatch=( $strPth_patternMatch ) #--- expand the pattern match; get the first value of the pattern match
27
  strPth_parentFld=$(dirname $strPth_filMatch) #--- get the parent dir of the first file match
28
  strPth_mdlFile=${@: -1} #--- Note: this gets the last arg; otherwise the 2nd arg would be an iteration of the 1st arg wildcard
29
 
30
+ strpth_pwd=$(pwd)
31
+ strpth_scriptLoc=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
32
+ strpth_scrHome="${strpth_scriptLoc}/../"
33
+ strpth_appHome="${strpth_scrHome}/../"
34
+
35
  #echo "TRACE: strPth_patternMatch= $strPth_patternMatch"
36
  #echo "TRACE: strPth_filMatch= $strPth_filMatch"
37
  #echo "TRACE: strPth_parentFld= $strPth_parentFld"
 
40
  #--- reconstitute model
41
  #--- Note: cat command does not work with single-quote literals; do not reapply single quotes
42
  #echo "cat ${strPth_patternMatch} > ${strPth_mdlFile}"
43
+ echo -e "INFO:\t Joining model binary ..."
44
  cat ${strPth_patternMatch} > ${strPth_mdlFile}
45
+ echo -e "INFO:\t Done ...\n"
{bin β†’ scripts}/models/util_splitModel.sh RENAMED
@@ -13,13 +13,24 @@ blkHeader
13
  #none
14
 
15
 
16
- #--- initialization
17
  #--- $1: first arg; the source model file; eg ./bin/models/model.pth
18
  #--- $n: last arg; dest model path; eg. ./test_model_folder
19
  strPth_mdlFile=$1
20
  strPth_mdlFolder=$2
21
  strPrefix='/model_'
22
 
 
 
 
 
 
 
 
 
 
 
 
23
  #echo "TRACE: strPth_mdlFile= $strPth_mdlFile"
24
  echo "TRACE: strPth_mdlFolder= $strPth_mdlFolder"
25
 
@@ -29,3 +40,5 @@ mkdir -p $strPth_mdlFolder
29
  #--- split the model into smaller chunks
30
  echo "split -b 10M $strPth_mdlFile $strPth_mdlFolder$strPrefix"
31
  split -b 10M $strPth_mdlFile $strPth_mdlFolder$strPrefix
 
 
 
13
  #none
14
 
15
 
16
+ #--- initialization/configuration
17
  #--- $1: first arg; the source model file; eg ./bin/models/model.pth
18
  #--- $n: last arg; dest model path; eg. ./test_model_folder
19
  strPth_mdlFile=$1
20
  strPth_mdlFolder=$2
21
  strPrefix='/model_'
22
 
23
+ if [ -z "$strPth_mdlFile" ] || [ -z "$strPth_mdlFolder" ]; then
24
+ echo "WARN: no args provided. Exiting script."
25
+ exit
26
+ fi
27
+
28
+ strpth_pwd=$(pwd)
29
+ strpth_scriptLoc=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
30
+ strpth_scrHome="${strpth_scriptLoc}/../"
31
+ #strpth_ignHome="${strpth_scrHome}/../"
32
+ strpth_appHome="${strpth_scrHome}/../"
33
+
34
  #echo "TRACE: strPth_mdlFile= $strPth_mdlFile"
35
  echo "TRACE: strPth_mdlFolder= $strPth_mdlFolder"
36
 
 
40
  #--- split the model into smaller chunks
41
  echo "split -b 10M $strPth_mdlFile $strPth_mdlFolder$strPrefix"
42
  split -b 10M $strPth_mdlFile $strPth_mdlFolder$strPrefix
43
+
44
+ echo -e "INFO:\t Done ...\n"
util_startLocal_streamlitFastApi.sh β†’ scripts/streamlitFastApi/util_local_runStreamlitFastApi.sh RENAMED
@@ -1,21 +1,25 @@
1
  #!/bin/bash
2
 
3
  #--- Note: this file is designed to run locally and within docker to prep the environment
 
 
 
 
4
  #--- for volume initialization; ensure folders are in place; assume: we are in the /app folder
5
- #mkdir -p data/demo_tiles/raw
6
- #mkdir -p data/tiles/raw data/tiles/pred data/tiles/grad_bg data/tiles/grad_wt data/tiles/grad_vt
7
- #mkdir -p data/wsi/raw
8
 
9
  #--- for streamlit; external 49400; internal 39400
10
  echo "INFO: starting streamlit ..."
11
- streamlit run app.py --server.port=49400 --server.maxUploadSize=2000 &
12
 
13
  #--- for fastapi; external 49500; internal 39500
14
  echo "INFO: starting fastapi ..."
15
- uvicorn main:app --reload --workers 1 --host 0.0.0.0 --port 49500 &
16
 
17
  #--- wait for any process to exit
18
  wait -n
19
 
20
  #--- Exit with status of process that exited first
21
- exit $?
 
1
  #!/bin/bash
2
 
3
  #--- Note: this file is designed to run locally and within docker to prep the environment
4
+ #--- Entry: this script is assumed to run from the /app root folder
5
+ #--- Usage: ./scripts/util_local_runStreamlitFastApi.sh
6
+ echo -e "INFO(util_local_runStreamlitFastApi):\t Initializing ..."
7
+
8
  #--- for volume initialization; ensure folders are in place; assume: we are in the /app folder
9
+ mkdir -p data/demo_tiles/raw
10
+ mkdir -p data/tiles/raw data/tiles/pred data/tiles/grad_bg data/tiles/grad_wt data/tiles/grad_vt
11
+ mkdir -p data/wsi/raw
12
 
13
  #--- for streamlit; external 49400; internal 39400
14
  echo "INFO: starting streamlit ..."
15
+ streamlit run app.py --server.port=39400 --server.maxUploadSize=2000 &
16
 
17
  #--- for fastapi; external 49500; internal 39500
18
  echo "INFO: starting fastapi ..."
19
+ uvicorn main:app --reload --workers 1 --host 0.0.0.0 --port 39500 &
20
 
21
  #--- wait for any process to exit
22
  wait -n
23
 
24
  #--- Exit with status of process that exited first
25
+ exit $?
scripts/util.sh ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ #--- Note: this file acts as a bash function library
4
+
5
+
6
+ <<blockComment
7
+ Name:
8
+ Usage:
9
+ PreReqs:
10
+ blockComment
11
+
12
+
13
+
14
+ #--- declarations
15
+ <<blockComment
16
+ function utl_trace_config (aryConfigVars) {
17
+ for each strConfig in aryConfigVars
18
+ trace_var("kstr_defDkrHubId")
19
+ #echo "TRACE: kstr_defDkrHubId = ${kstr_defDkrHubId}"
20
+ echo "TRACE: kstr_defDkrImageName = ${kstr_defDkrImageName}"
21
+ echo "TRACE: kstr_defDkrTagVersion = ${kstr_defDkrTagVersion}"
22
+ echo "TRACE: kstr_defDkrTagStage = ${kstr_defDkrTagStage}"
23
+ echo "TRACE: kstr_dkrImg = ${kstr_dkrImg}"
24
+ echo "TRACE: kstr_dkrCtr = ${kstr_dkrCtr}"
25
+ }
26
+ blockComment
27
+
28
+
29
+ function utl_strRepeat {
30
+ #--- Usage1: utl_strRepeat <repeatVal> <repeatCount> <returnVar>
31
+ local strRptVal="${1:-null}" #--- value to repeat
32
+ local intRptCount="${2:-1}" #--- repeat count; num times to repeat text
33
+ local varReturn="${3:-output}" #--- output var
34
+ local strTemp #--- temp variable
35
+ printf -v strTemp '%*s' "$intRptCount"
36
+ printf -v "$varReturn" '%s' "${strTemp// /$strRptVal}"
37
+ }
38
+
39
+
40
+ function utl_valIsEmpty {
41
+ #--- Usage1: utl_valIsEmpty <val> | "<val>"
42
+ #--- Usage2: returnVal=$(utl_valIsEmpty <val> | "<val>")
43
+ local strTestVal="${1:-null}" #--- test value
44
+ local __blnReturn=NULL #--- output var
45
+
46
+ #echo -e "TRACE: \t $1\n"
47
+ # if [ ! -z "$strTestVal" -a "$strTestVal" != " " -a "$strTestVal" != "" ]; then #--- check for empty string
48
+ if [ ! -z "$strTestVal" ]; then
49
+ __blnReturn=false
50
+ if [ "$strTestVal" == " " ] || [ "$strTestVal" == "" ]; then
51
+ __blnReturn=true
52
+ else
53
+ if [ "$strTestVal" == null ] || [ "$strTestVal" == NULL ] || [ "$strTestVal" == Null ]; then
54
+ __blnReturn=true
55
+ fi
56
+ fi
57
+ else
58
+ __blnReturn=true
59
+ fi
60
+ echo "$__blnReturn"
61
+ }
62
+
63
+
64
+ function utl_varIsEmpty {
65
+ local strTestVar="${1:-null}" #--- test variable
66
+ local __blnReturn=false #--- output var
67
+
68
+ if [ -z "$strTestVar" ]; then #--- check for empty string
69
+ __blnReturn=true
70
+ fi
71
+ echo "$__blnReturn"
72
+ }
73
+
74
+
75
+ function utl_getScriptLoc {
76
+ local __blnReturn=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
77
+ echo "$__blnReturn"
78
+ }
79
+
80
+
81
+ function utl_logMsg {
82
+ #--- format: <date/time> \ t <logType> <logLevel> \t <preMsg> \t <Msg> \t <postMsg> \t <varName> \t <varValue>
83
+ local blnLogOn="${1:-true}" #--- true: log, false: do not log
84
+ local strLogType="${2:-LOG}" #--- INFO, ERR, WARN, TRACE, TRMOD, TRFXN, EXCPT, DEBUG
85
+ local strLogLevel="${3:-0}" #--- Depth of log (tab indent)
86
+ local strMsgPrefix="${4:-null}" #---
87
+ local strMsg="${5:-null}" #---
88
+ local strMsgPostfix="${6:-null}" #---
89
+ local strVarName="${7:-null}" #---
90
+ local strVarVal="${8:-null}" #---
91
+
92
+ #local blnIsEmpty=$(utl_valIsEmpty $strMsg)
93
+ #echo -e "TRACE: blnIsEmpty=$blnIsEmpty \t $strMsg \t $(blnEmpty==false) \t $(blnEmpty=='false')"
94
+ if $(utl_valIsEmpty $strMsgPrefix); then strMsgPrefix=""; else strMsgPrefix="$strMsgPrefix \t"; fi
95
+ if $(utl_valIsEmpty $strMsg); then strMsg=""; else strMsg="$strMsg \t"; fi
96
+ if $(utl_valIsEmpty $strMsgPostfix); then strMsgPostfix=""; else strMsgPostfix="$strMsgPostfix \t"; fi
97
+ if $(utl_valIsEmpty $strVarName); then strVarName=""; else strVarName="$strVarName = "; fi
98
+ if $(utl_valIsEmpty $strVarVal); then strVarVal=""; else strVarVal="$strVarVal"; fi
99
+
100
+ local intTabLevel="$strLogLevel"
101
+ #echo "TRACE (utl_logMsg): $strLogLevel"
102
+ utl_strRepeat "\t" $intTabLevel strTabLevel
103
+ #echo "TRACE (utl_logMsg): $strTabLevel"
104
+
105
+ if $(utl_valIsEmpty $strLogLevel); then strLogLevel="\b"; strTabLevel=""; fi
106
+ if [ "$strLogLevel" -eq "0" ]; then strLogLevel="\b"; strTabLevel=""; fi
107
+
108
+ #if $($strLogLevel==0); then strLogLevel=""; strTabLevel=""; fi
109
+
110
+ if [ "$blnLogOn" ]; then
111
+ echo -e "$strTabLevel $strLogType $strLogLevel: \t $strMsgPrefix $strMsg $strMsgPostfix $strVarName $strVarVal"
112
+ fi
113
+ }
114
+
115
+
116
+ function utl_logTrace {
117
+ #--- format: <date/time> \ t <logType> <logLevel> \t <preMsg> \t <Msg> \t <postMsg> \t <varName> \t <varValue>
118
+ local blnLogOn="${1:-true}" #--- true: log, false: do not log
119
+ local strLogType="TRACE" #--- INFO, ERR, WARN, TRACE, TRMOD, TRFXN, EXCPT, DEBUG
120
+ local strLogLevel="${2:-0}" #--- Depth of log (tab indent)
121
+ local strMsg="${3:-null}" #---
122
+
123
+ utl_logMsg $blnLogOn "$strLogType" "$strLogLevel" null "$strMsg" null null null
124
+ }
125
+
126
+ function utl_logInfo {
127
+ #--- format: <date/time> \ t <logType> <logLevel> \t <preMsg> \t <Msg> \t <postMsg> \t <varName> \t <varValue>
128
+ local blnLogOn="${1:-true}" #--- true: log, false: do not log
129
+ local strLogType="INFO" #--- INFO, ERR, WARN, TRACE, TRMOD, TRFXN, EXCPT, DEBUG
130
+ local strLogLevel="${2:-0}" #--- Depth of log (tab indent)
131
+ local strMsg="${3:-null}" #---
132
+
133
+ utl_logMsg $blnLogOn "$strLogType" "$strLogLevel" null "$strMsg" null null null
134
+ }
135
+
136
+
137
+ function utl_trace_var {
138
+ local strVarName="${1:-null}" #---
139
+ local strVarVal="${2:-null}" #---
140
+ #echo "\t(util.utl_trace_var) TRACE: \t strVarName = ${strVarName}"
141
+
142
+ #kstr_tracePtn="TRACE: <var> = \${<var>}"
143
+ #str_tracePtn="${kstr_tracePtn//<var>/"$strVarName"}" #--- bash replace all occurrences
144
+ #echo ${str_tracePtn}
145
+ #echo "TRACE (utl_trace_var): $strVarName = $strVarVal"
146
+ #utl_logMsg true "TRACE" 0 "msgPrefix" "msg" "msgPostfix" $strVarName $strVarVal
147
+ utl_logMsg true "TRACE" 0 null null null $strVarName $strVarVal
148
+ }
uix/lit_sidebar.py CHANGED
@@ -5,12 +5,14 @@ from uix import lit_packages
5
  from uix.pages import lit_home, lit_about, lit_diagnosis
6
  from uix.pages import lit_qaConfigCheck
7
 
 
 
8
 
9
  #--- alt define sidebar pages
10
  m_aryPages = {
11
  "Home": lit_home, #--- TODO: update
12
- "Diagnosis: One Tile": lit_diagnosis,
13
- #"QA: File Check": lit_qaConfigCheck,
14
  "About": lit_about
15
  }
16
 
@@ -26,71 +28,16 @@ def init():
26
  with st.sidebar:
27
  kstrUrl_image = "bin/images/logo_omdena_saudi.png"
28
  st.sidebar.image(kstrUrl_image, width=200)
29
- #st.sidebar.markdown('Omdena Saudi - Liver HCC Diagnosis with XAI')
30
-
31
 
32
- #--- init checkboxes
33
- strKey = st.sidebar.radio("", list(m_aryPages.keys()))
34
  pagSel = m_aryPages[strKey]
35
  writePage(pagSel)
36
 
37
 
38
-
39
- def init_selectBox():
40
- #--- init module array of page names, and descr
41
- init_modDescrAry()
42
-
43
- # Display the sidebar with a menu of apps
44
- kstrMsg = """
45
- __Claims Anomaly Views__
46
- """
47
- with st.sidebar:
48
- st.markdown('---')
49
- st.markdown(kstrMsg)
50
- page = st.selectbox('Select:', m_aryModNames, format_func=fmt_modName)
51
-
52
- #--- display sidebar footer
53
- with st.sidebar:
54
- st.markdown('---')
55
- st.write('Developed by Chavarria, McKone, Sharma')
56
- st.write('Contact at iain.mckone@gmail.com')
57
-
58
- # Run the chosen app
59
- m_aryMods[m_aryModNames.index(page)].run()
60
-
61
-
62
-
63
- def init_modDescrAry():
64
- #--- init global array of page names, and descr
65
- #--- note: you need to specify global scope for fxns to access module-level variables
66
- global m_aryMods
67
- global m_aryDescr
68
-
69
- m_aryMods = []
70
- m_aryDescr = []
71
- for modName in m_aryModNames:
72
- modTemp = importlib.import_module('.'+modName,'uix')
73
- m_aryMods.append(modTemp)
74
-
75
- #--- If the module has a description attribute use that in the
76
- #--- select box otherwise use the module name
77
- try:
78
- m_aryDescr.append(modTemp.description)
79
- except:
80
- m_aryDescr.append(modName)
81
-
82
-
83
-
84
- #--- display the app descriptions instead of the module names in the selctbox
85
- def fmt_modName(strName):
86
- global m_aryModNames
87
- global m_aryDescr
88
- return m_aryDescr[m_aryModNames.index(strName)]
89
-
90
-
91
-
92
  def writePage(uixFile):
93
  #--- writes out the page for the selected combo
94
-
95
  # _reload_module(page)
96
  uixFile.run()
 
 
5
  from uix.pages import lit_home, lit_about, lit_diagnosis
6
  from uix.pages import lit_qaConfigCheck
7
 
8
+ m_kblnTraceOn=False
9
+
10
 
11
  #--- alt define sidebar pages
12
  m_aryPages = {
13
  "Home": lit_home, #--- TODO: update
14
+ "Diagnosis: Single Tile": lit_diagnosis,
15
+ #"QA: File Check": lit_qaConfigCheck,
16
  "About": lit_about
17
  }
18
 
 
28
  with st.sidebar:
29
  kstrUrl_image = "bin/images/logo_omdena_saudi.png"
30
  st.sidebar.image(kstrUrl_image, width=200)
 
 
31
 
32
+ #--- get radio selection
33
+ strKey = st.sidebar.radio("rdoPageSel", list(m_aryPages.keys()), label_visibility="hidden")
34
  pagSel = m_aryPages[strKey]
35
  writePage(pagSel)
36
 
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  def writePage(uixFile):
39
  #--- writes out the page for the selected combo
40
+
41
  # _reload_module(page)
42
  uixFile.run()
43
+
uix/pages/lit_about.py CHANGED
@@ -10,13 +10,17 @@ def run():
10
  #st.experimental_memo.clear() #--- try to clear cache each time this page is hit
11
  #st.cache_data.clear()
12
 
13
- st.markdown('### About')
14
- st.markdown('### Omdena Saudi: Liver HCC Diagnosis with XAI')
15
- st.markdown('#### Chapter Lead: Dr. Shai')
16
-
 
 
 
17
  st.markdown(
18
  """
19
  About page
20
  """,
21
  unsafe_allow_html=True,
22
- )
 
 
10
  #st.experimental_memo.clear() #--- try to clear cache each time this page is hit
11
  #st.cache_data.clear()
12
 
13
+ #st.markdown('### About')
14
+ #st.markdown('### Omdena Saudi Arabia')
15
+ #st.markdown('### Detecting Liver Cancer from Histopathology WSI Using Deep Learning and Explainability')
16
+ #st.markdown('#### Dr. Shaista Hussain (Saudi Arabia Chapter Lead)')
17
+ #st.markdown('##### Deployment Lead: Iain McKone')
18
+ st.markdown('##### Project Url: https://github.com/OmdenaAI/saudi-arabia-histopathology-detection')
19
+ '''
20
  st.markdown(
21
  """
22
  About page
23
  """,
24
  unsafe_allow_html=True,
25
+ )
26
+ '''
uix/pages/lit_diagnosis.py CHANGED
@@ -18,7 +18,7 @@ from pytorch_grad_cam.utils.image import show_cam_on_image
18
  import lib.utils as libUtils
19
 
20
  import sys
21
- import os
22
 
23
  description = "Diagnosis"
24
  m_kblnTraceOn = True #--- enable/disable module level tracing
@@ -42,6 +42,25 @@ backbone_model_name = DEFAULT_BACKBONE_MODEL
42
 
43
 
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  def run():
46
  #--- note: in python, you need to specify global scope for fxns to access module-level variables
47
  global m_kbln_TraceOn
@@ -50,36 +69,59 @@ def run():
50
 
51
  #--- page settings
52
  if (m_kblnTraceOn): print("TRACE1 (litDiagnosis.run): Initialize Page Settings ...")
53
- st.header("Single Tile Diagnosis")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
 
56
  #--- provide file drag/drop capability
57
  m_blnDisableDragDrop = False
58
- if(not m_blnDisableDragDrop):
59
  #btnSave = st.button("Save")
60
- imgDropped = st.file_uploader("Upload a single Tile", type=["png", "jpg", "tif", "tiff", "img"])
61
- m_blnDisableDragDrop = (imgDropped is None)
 
 
 
 
 
62
 
63
 
64
- #if (True):
 
 
65
  try:
66
-
 
 
 
 
67
  #--- show:
68
  #if (m_kblnTraceOn): print("TRACE (litDiagnosis.run): load WSI ...")
69
- if (m_blnDisableDragDrop):
70
  #--- load wsi
71
- print("")
72
- else:
73
- #--- display uploaded file details
74
- if (m_kblnTraceOn): print("TRACE1 (litDiagnosis.run): Print upload file details ...")
75
- st.write(
76
- "FileName:", "&nbsp;&ensp;&emsp;", imgDropped.name, "\n",
77
- "FileType:", "&nbsp;&emsp;&emsp;", imgDropped.type, "\n"
78
- )
79
 
80
  #--- display diagnosis results ... format (vertical)
81
- #showDiagnosis_vert(imgDropped)
82
- showDiagnosis_horiz(imgDropped)
83
 
84
  except TypeError as e:
85
  print("ERROR (litDiagnosis.run_typeError1): ", e)
@@ -110,23 +152,24 @@ def showImg_wsi(img):
110
 
111
 
112
  def readyModel_getPreds(imgDropped):
113
- print("TRACE: save raw tile ...")
 
114
  strPth_tilRaw = save_tilRaw(imgDropped)
115
 
116
  #--- ready the model
117
- print("TRACE: ready base model ...")
118
  mdlBase = readyBaseModel()
119
- print("TRACE: ready model with weights ...")
120
  mdlWeights = readyModelWithWeights(mdlBase)
121
- print("TRACE: ready model with xai ...")
122
  mdlXai = readyModelWithXAI(mdlWeights)
123
 
124
  #--- get the XAI weighted prediction
125
- print("TRACE: get xai weighted pred ...")
126
  output_pred, tns_batch = predXai_tile(mdlXai, strPth_tilRaw)
127
 
128
  #--- get the GRADCAM predictions
129
- print("TRACE: get GRADCAM preds ...")
130
  cam_img_bg, cam_img_wt, cam_img_vt = predGradCam_tile(output_pred, mdlXai, tns_batch)
131
 
132
  print("TRACE: return readyModel_getPreds ...")
@@ -164,11 +207,16 @@ def showCol_rawTil(colRaw, strPth_tilRaw):
164
  print("TRACE3: showCol_rawTil ...")
165
  colRaw.image(strPth_tilRaw, width=400, use_column_width=True)
166
 
167
-
 
 
168
  def showCol_predTil(colPred, xai_pred, strPth_tilRaw):
169
  kstrPth_tilePred = "data/tiles/pred/"
170
  strFilName = os.path.basename(strPth_tilRaw)
171
  strFil_tilePred = kstrPth_tilePred + strFilName
 
 
 
172
 
173
  print("TRACE3: showCol_predTil2 ... ", strFil_tilePred)
174
  argmax_mask = torch.argmax(xai_pred, dim=0)
@@ -217,10 +265,28 @@ def showDiagnosis_vert(imgDropped):
217
  colImage.image(lstImages[imgIdx], width=400, use_column_width=True)
218
 
219
 
 
 
 
 
 
 
 
220
  def save_tilRaw(imgDropped):
 
221
  #--- copy the uploaded raw Tile to data/tiles/raw
222
  kstrPth_tileRaw = "data/tiles/raw/"
223
  strFil_tileRaw = kstrPth_tileRaw + imgDropped.name
 
 
 
 
 
 
 
 
 
 
224
  with open(strFil_tileRaw,"wb") as filUpload:
225
  filUpload.write(imgDropped.getbuffer())
226
  print("TRACE: uploaded file saved to ", strFil_tileRaw)
 
18
  import lib.utils as libUtils
19
 
20
  import sys
21
+ import os, random, io
22
 
23
  description = "Diagnosis"
24
  m_kblnTraceOn = True #--- enable/disable module level tracing
 
42
 
43
 
44
 
45
+ def image_toBytesIO(image: Image) -> bytes:
46
+ #--- BytesIO is a file-like buffer stored in memory
47
+ imgByteArr = io.BytesIO()
48
+
49
+ #--- image.save expects a file-like as a argument
50
+ image.save(imgByteArr, format=image.format)
51
+
52
+ return imgByteArr
53
+
54
+
55
+ def image_toByteArray(image: Image) -> bytes:
56
+ #--- convert image to bytesIO
57
+ imgByteArr = image_toBytesIO(image)
58
+
59
+ #--- Turn the BytesIO object back into a bytes object
60
+ imgByteArr = imgByteArr.getvalue()
61
+ return imgByteArr
62
+
63
+
64
  def run():
65
  #--- note: in python, you need to specify global scope for fxns to access module-level variables
66
  global m_kbln_TraceOn
 
69
 
70
  #--- page settings
71
  if (m_kblnTraceOn): print("TRACE1 (litDiagnosis.run): Initialize Page Settings ...")
72
+ #st.header("Single Tile Diagnosis")
73
+ st.markdown("#### Single Tile Diagnosis")
74
+
75
+ #--- allow the user to select a random sample
76
+ imgUploaded = None
77
+ if st.button("Random Sample"):
78
+ #--- get a random sample file
79
+ strPth_sample = libUtils.pth_dtaTileSamples
80
+ strFil_sample = random.choice(os.listdir(strPth_sample))
81
+ strFullPth_sample = os.path.join(strPth_sample, strFil_sample)
82
+
83
+ print("INFO (litDiagnosis.run): sample file selected ... ", strFullPth_sample)
84
+
85
+ #--- display; convert file image to bytesIO
86
+ imgSample = Image.open(strFullPth_sample)
87
+ imgSample = image_toBytesIO(imgSample)
88
+ imgUploaded = imgSample
89
+ imgUploaded.name = strFil_sample
90
+ imgUploaded.type = os.path.splitext(strFil_sample)[1]
91
 
92
 
93
  #--- provide file drag/drop capability
94
  m_blnDisableDragDrop = False
95
+ #if(not m_blnDisableDragDrop):
96
  #btnSave = st.button("Save")
97
+ imgDropped = st.file_uploader("Upload a single Tile",
98
+ type=["png", "jpg", "tif", "tiff", "img"],
99
+ accept_multiple_files=False )
100
+ #m_blnDisableDragDrop = (imgDropped is None)
101
+ #--- <class 'streamlit.runtime.uploaded_file_manager.UploadedFile'>
102
+ if (imgDropped is not None):
103
+ imgUploaded = imgDropped
104
 
105
 
106
+ if (imgUploaded is None):
107
+ if (m_kblnTraceOn): print("ERROR (litDiagnosis.run): imgUploaded is None ...")
108
+ else:
109
  try:
110
+ #--- display uploaded file details
111
+ if (m_kblnTraceOn): print("TRACE1 (litDiagnosis.run): Print uploaded file details ...")
112
+ st.write("FileName:", "&nbsp;&ensp;&emsp;", imgUploaded.name)
113
+ st.write("FileType:", "&nbsp;&emsp;&emsp;", imgUploaded.type)
114
+
115
  #--- show:
116
  #if (m_kblnTraceOn): print("TRACE (litDiagnosis.run): load WSI ...")
117
+ #if (m_blnDisableDragDrop):
118
  #--- load wsi
119
+ # print("")
120
+ #else:
 
 
 
 
 
 
121
 
122
  #--- display diagnosis results ... format (vertical)
123
+ #showDiagnosis_vert(imgUploaded)
124
+ showDiagnosis_horiz(imgUploaded)
125
 
126
  except TypeError as e:
127
  print("ERROR (litDiagnosis.run_typeError1): ", e)
 
152
 
153
 
154
  def readyModel_getPreds(imgDropped):
155
+ print("TRACE: readyModel_getPreds ...")
156
+ print("INFO: save raw tile ...")
157
  strPth_tilRaw = save_tilRaw(imgDropped)
158
 
159
  #--- ready the model
160
+ print("INFO: ready base model ...")
161
  mdlBase = readyBaseModel()
162
+ print("INFO: ready model with weights ...")
163
  mdlWeights = readyModelWithWeights(mdlBase)
164
+ print("INFO: ready model with xai ...")
165
  mdlXai = readyModelWithXAI(mdlWeights)
166
 
167
  #--- get the XAI weighted prediction
168
+ print("INFO: get xai weighted pred ...")
169
  output_pred, tns_batch = predXai_tile(mdlXai, strPth_tilRaw)
170
 
171
  #--- get the GRADCAM predictions
172
+ print("INFO: get GRADCAM preds ...")
173
  cam_img_bg, cam_img_wt, cam_img_vt = predGradCam_tile(output_pred, mdlXai, tns_batch)
174
 
175
  print("TRACE: return readyModel_getPreds ...")
 
207
  print("TRACE3: showCol_rawTil ...")
208
  colRaw.image(strPth_tilRaw, width=400, use_column_width=True)
209
 
210
+ #--- Dark blue -> Background
211
+ # Brown -> Whole tumor
212
+ # Green/Aqua -> Viable tumor
213
  def showCol_predTil(colPred, xai_pred, strPth_tilRaw):
214
  kstrPth_tilePred = "data/tiles/pred/"
215
  strFilName = os.path.basename(strPth_tilRaw)
216
  strFil_tilePred = kstrPth_tilePred + strFilName
217
+
218
+ #--- make sure the dir exists
219
+ ensureDirExists(kstrPth_tilePred)
220
 
221
  print("TRACE3: showCol_predTil2 ... ", strFil_tilePred)
222
  argmax_mask = torch.argmax(xai_pred, dim=0)
 
265
  colImage.image(lstImages[imgIdx], width=400, use_column_width=True)
266
 
267
 
268
+ def ensureDirExists(strPth):
269
+ blnExists = os.path.exists(strPth)
270
+ if not blnExists:
271
+ os.makedirs(strPth)
272
+ print("TRACE: creating dir ... ", strPth)
273
+
274
+
275
  def save_tilRaw(imgDropped):
276
+ print("TRACE: save_tilRaw ...")
277
  #--- copy the uploaded raw Tile to data/tiles/raw
278
  kstrPth_tileRaw = "data/tiles/raw/"
279
  strFil_tileRaw = kstrPth_tileRaw + imgDropped.name
280
+ print("TRACE: save_tilRaw.file ... ", strFil_tileRaw)
281
+
282
+ #--- make sure the dir exists
283
+ ensureDirExists(kstrPth_tileRaw)
284
+
285
+ #--- check if the file already exists; delete
286
+ if (os.path.isfile(strFil_tileRaw)):
287
+ print("WARN: save_tilRaw.file exists; delete ... ", strFil_tileRaw)
288
+ os.remove(strFil_tileRaw)
289
+
290
  with open(strFil_tileRaw,"wb") as filUpload:
291
  filUpload.write(imgDropped.getbuffer())
292
  print("TRACE: uploaded file saved to ", strFil_tileRaw)
uix/pages/lit_home.py CHANGED
@@ -7,21 +7,60 @@ def run():
7
  print("\nINFO (lit_home.run) loading ", description, " page ...")
8
 
9
 
10
- st.markdown('### Home')
11
- st.markdown('### Omdena Saudi: Liver HCC Diagnosis with XAI')
12
- st.markdown('#### Chapter Lead: Dr. Shai')
 
13
  st.markdown('\
14
- <background> \
15
- ')
16
-
17
- st.markdown('\
18
- <basis> \
19
- ')
20
-
 
 
 
 
 
 
 
 
 
 
 
21
  st.markdown('\
22
- <claim> \
23
- ')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  st.markdown(
26
  """
27
 
@@ -29,4 +68,9 @@ def run():
29
 
30
  """,
31
  unsafe_allow_html=True,
32
- )
 
 
 
 
 
 
7
  print("\nINFO (lit_home.run) loading ", description, " page ...")
8
 
9
 
10
+ #st.markdown('### Home')
11
+ #st.markdown('### Omdena Saudi Arabia')
12
+ #st.markdown('### Detecting Liver Cancer from Histopathology WSI Using Deep Learning and Explainability')
13
+ st.markdown('#### Background ')
14
  st.markdown('\
15
+ Hepatocellular Carcinoma (HCC) is a primary liver malignancy, with \
16
+ alarming global impact. It is the 4th most common cause of cancer \
17
+ mortality worldwide, and the 6th most common malignancy overall. \
18
+ \
19
+ A patient\'s prognosis increases markedly with the speed of diagnosis \
20
+ and treatment, however the rates of occurrence are increasing at an \
21
+ alarming rate which will commensurately challenge the medical \
22
+ community. \
23
+ \
24
+ There are already several tools and technologies available to assist \
25
+ pathologists, however the current approach is ultimately constrained by \
26
+ a number of factors including: the rising demand, a limited supply \
27
+ of skilled specialists, the time required to grow/replenish this talent \
28
+ pool, and human factors which influence quality, accuracy, consistency, \
29
+ and speed (timeliness). \
30
+ ')
31
+
32
+ st.markdown('#### Claim ')
33
  st.markdown('\
34
+ It is the desire of this project team to increase the prognosis of \
35
+ hepatocellular cancer patients.\
36
+ \
37
+ Machine Learning techniques, specifically Deep Learning and \
38
+ Explainability (XAI) show promise in mimic\'ing the role of the \
39
+ pathologist. \
40
+ \
41
+ MLOps promises to establish a baseline for performance\
42
+ and a basis for continuous process improvement. This could greatly \
43
+ reduce human factor elements while accelerating the times and \
44
+ increasing the volumes of response.\
45
+ \
46
+ As a minimum, an ML application can serve as a supplement to the\
47
+ pathologist, a teaching aide, a verification tool, or as a framework\
48
+ for community collaboration and the advancement of quality diagnosis.\
49
+ ')
50
 
51
+ st.markdown('#### Objectives ')
52
+ st.markdown('\
53
+ A key objective of this project is to produce a deployed app that will\
54
+ enable pathologists to upload a digital liver histopathology slide\
55
+ image and then receive an output that classifies the segment as\
56
+ malignant (or not). \
57
+ \
58
+ The utilization of Machine Learning and Explainability Techniques \
59
+ to the traditional process of Liver Histopathology and HCC Diagnosis \
60
+ could serve to greatly reduce the time to diagnosis and treatment. \
61
+ \
62
+ ')
63
+ '''
64
  st.markdown(
65
  """
66
 
 
68
 
69
  """,
70
  unsafe_allow_html=True,
71
+ )
72
+ <style>
73
+ # MainMenu {visibility: hidden;}
74
+ footer {visibility: hidden;}
75
+ </style>
76
+ '''