diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5a319b5..d461870 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,22 +1,29 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/python { - "name": "vpipe-frontend", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye" + "name": "vpipe-frontend", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye", - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [8000], - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "pip3 install --user -r requirements.txt", + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pip3 install --user -r requirements.txt", + "customizations": { + "vscode": { + "settings": { + "editor.rulers": [80] + } + } + } - // Configure tool-specific properties. - // "customizations": {}, + // Configure tool-specific properties. + // "customizations": {}, - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" } diff --git a/app.py b/app.py index 8d18d6a..43a2ebe 100644 --- a/app.py +++ b/app.py @@ -2,11 +2,15 @@ import index import mutation_freq import variant_deconv +import resistance_mut +import resistance_mut_silo PAGES = { "Home": {"module": index}, "Mutation Frequency": {"module": mutation_freq}, "Variant Deconvolution": {"module": variant_deconv}, + "Resistance Mutations (clinical)": {"module": resistance_mut}, + "Resistance Mutations (ww)": {"module": resistance_mut_silo} } def sidebar(): diff --git a/config.yaml b/config.yaml index 50ceba4..b579ffb 100644 --- a/config.yaml +++ b/config.yaml @@ -1,2 +1,3 @@ server: - ip_address: "http://68.221.168.92:8000" \ No newline at end of file + ip_address: "http://68.221.168.92:8000" + lapis_address: "http://localhost:8080" \ No newline at end of file diff --git a/data/3CLpro_inhibitors_datasheet.csv b/data/3CLpro_inhibitors_datasheet.csv new file mode 100644 index 0000000..d7f787f --- /dev/null +++ b/data/3CLpro_inhibitors_datasheet.csv @@ -0,0 +1,72 @@ +Mutation,NTV: fold,NTV: pocket,ENS: fold,fitness,in patient,in vitro,Prevalence +T21I,1.5,,1.6,1.6,,12,0.1% +T25A,12.6,,87.7,,,,0.002% +T25N,0.8,,22.9,,,,0.00006% +T45I,1.6,1,4.8,,,,0.02% +D48Y,2,1,5.9,,,,0.0005% +M49I,1.1,1,10.1,1.8,,,0.02% +M49L,1.4,1,40.9,1.2,,2,0.0002% +M49T,0.8,1,3.6,1.4,,,0.0005% +M49del,2.8,1,,0.5,,, +L50F,1.5,1,1.1,2.3,1,9,0.04% +G138S,3.5,,,,,1,0.00008% +F140L,5.9,,,,,2,0.0001% +F140S,260,,,,,,0.00004% +N142D,1.5,1,3.2,1.1,,,0.0008% +N142L,2.5,1,,1.4,,,0.0001% +N142S,1.2,1,4.9,1.2,,,0.001% +G143S,147.7,1,15.6,0,,,0.00001% +S144A,7.3,1,17.2,0.6,,2,0.00009% +S144E,81.5,1,,0,,,0.00001% +S144L,1154.1,1,,0,,,0.00006% +S144P,2851.7,1,,0,,,0.00001% +C160F,1,,,0.7,,4,0.01% +M165R,384.2,1,,0,,,0.00001% +M165T,15.8,1,,0.1,,,0.00003% +E166A,10,1,6.3,0.1,1,5,0.00004% +E166G,6.2,1,,0.1,,,0.00004% +E166K,76.6,1,,0,,,0.00003% +E166Q,2.7,1,,1,,,0.00005% +E166V,287.5,1,50.3,0.1,5,3,0.0001% +L167F,7,1,12.8,0.3,,6,0.0002% +P168del,7,1,6.1,,,, +T169I,1.1,1,1.3,,,2,0.003% +H172L,898.8,1,,0,,,0.00001% +H172N,464.1,1,,0,,,0.00001% +H172Q,5.8,1,,0.3,,1,0.00004% +H172Y,24.2,1,,0.2,,2,0.00009% +A173T,2.5,,1.2,,,1,0.002% +A173V,6.4,,1.3,,,3,0.002% +V186A,,1,,,,2,0.0004% +R188G,38,1,,,,2,0.00009% +R188S,2.9,1,5.8,0.9,,,0.0007% +Q189I,4.2,1,,,,,0.00003% +Q189K,8.6,1,1.9,0.3,,,0.0003% +T190I,1.2,1,2.9,1.3,,,0.02% +A191T,1.2,1,4.6,1.7,,3,0.006% +A191V,1.6,1,3.6,1.9,,7,0.08% +Q192A,18.2,1,,0.2,,,0.0007% +Q192C,16.3,1,,0.1,,,0.00006% +Q192D,10.4,1,,0,,,0.00006% +Q192E,34.2,1,,0.1,,,0.00003% +Q192F,24.6,1,,0.3,,,0.00001% +Q192G,34.4,1,,0.1,,,0.00009% +Q192H,24.7,1,,0.1,,,0.00009% +Q192I,13.7,1,,0.2,,,0.00008% +Q192K,27.9,1,,0,,,0.0003% +Q192L,29,1,,0.2,,,0.0002% +Q192N,2.8,1,,0.1,,,0.00001% +Q192P,7.8,1,,0.1,,,0.0002% +Q192R,19.2,1,3.2,0.1,,1,0.0002% +Q192S,24.3,1,,0.1,,,0.0003% +Q192T,16.8,1,,0.1,,,0.0002% +Q192V,10.1,1,,0.1,,,0.0002% +Q192W,12.9,1,,0.1,,,0.00001% +Q192Y,384.2,1,,0,,,0.0001% +A193P,,,,,,2,0.0004% +A194S,3.3,,,,,1,0.002% +P252L,5.8,,1.3,,,5,0.004% +V297A,3,,,,,,0.00001% +S301P,,,,,,2,0.0002% +T304I,2.5,,1,,,8,0.007% +F305L,,,,,,2,0.001% \ No newline at end of file diff --git a/data/RdRP_inhibitors_datasheet.csv b/data/RdRP_inhibitors_datasheet.csv new file mode 100644 index 0000000..22ccd61 --- /dev/null +++ b/data/RdRP_inhibitors_datasheet.csv @@ -0,0 +1,20 @@ +Mutation,RDV: fold,in patient,in vitro,Prevalence +V166A,,,1,0.0008% +V166L,1.5,2,1,0.004% +N198S,,,1,0.01% +R285C,,2,,0.006% +A376V,12.6,,,0.00002% +A449V,,2,,0.07% +F480L,2,,1,0.0002% +D484Y,3.1,1,,0.0008% +A526V,,,1,0.04% +V557L,2,,1,0.0003% +G671S,1,2,,47% +S759A,2.6,,1,0% +V792I,2.6,3,1,0.002% +E796G,2.8,,1,0.0007% +C799F,3.4,,2,0.0009% +C799R,2.8,,1,0.00006% +E802A,3,,,0.0002% +E802D,6,1,1,0.002% +M924R,,2,,0.003% \ No newline at end of file diff --git a/data/spike_mAbs_datasheet.csv b/data/spike_mAbs_datasheet.csv new file mode 100644 index 0000000..dc0631d --- /dev/null +++ b/data/spike_mAbs_datasheet.csv @@ -0,0 +1,165 @@ +Mutation,BAM: fold,BAM: dms,ETE: fold,ETE: dms,CAS: fold,CAS: dms,IMD: fold,IMD: dms,CIL: fold,CIL: dms,TIX: fold,TIX: dms,SOT: fold,SOT: dms,BEB: fold,BEB: dms,REG: fold,AMU: fold,ROM: fold,ADI: fold,C135: fold,C135: dms,C144: fold,C144: dms,in patient,in vitro,Prevalence +P337H,,,,,,,,,,,,,6.3,1,,,,,,,,,,,6,,0.0008% +P337L,,,,,,,5,,,,,,186,0.997,,,,,,,,,,,10,1,0.003% +P337R,,,,,,,,,,,,,234,0.999,,,,,,,,,,,4,,0.0004% +P337S,,,,,,,,,,,,,1.8,0.999,,,,,,,,,,,22,,0.003% +P337T,,,,,,,,,,,,,8,0.992,,,,,,,,,,,,,0.001% +E340A,,,,,,,,,,,,,100,0.997,,,,,,,,,,,13,3,0.002% +E340D,,,,,,,,,,,,,14.8,0.988,,,,,,,,,,,23,,0.003% +E340G,,,,,,,,,,,,,22.6,0.986,,,,,,,,,,,1,,0.0008% +E340K,,,0.4,,,,,,,,,,5148,0.997,,,,,,,,,,,25,1,0.004% +E340Q,,,,,,,,,,,,,50,0.966,,,,,,,,,,,4,,0.0005% +E340V,,,,,,,,,,,,,200,,,,,,,,,,,,7,,0.001% +T345P,,,,,,,,,,,,,,0.991,,,,,,,,,,,,1,0.0001% +R346G,,,,,,,,,,0.606,,,0.9,,,,,,,,,0.697,,,,4,0.005% +R346I,,,,,,,,,200,0.728,,,1.7,,,,,,,,,0.734,,,2,3,0.01% +R346K,1.3,,2.4,,1.1,,2.9,,2.6,,2.2,,1.4,,0.7,,0.3,0.8,21,0.8,2296.4,0.82,0.8,,2,2,8.9% +R346S,,,1.8,,,,,,,0.763,,,1.8,,0.4,,,,,,2700,0.813,0.9,,2,1,0.03% +R346T,,,,,,,,,,0.9,,,1.3,,,,,,,,,0.804,,,3,,0.006% +K356Q,,,,,,,,,,,,,0.9,0.106,,,,,,,,,,,,,0.001% +K356T,,,,,,,,,,,,,5.9,0.9,,,,,,,,,,,3,,0.0008% +S371F,0.9,,143,,13.5,,87,,1.3,,26,,13.3,,2.4,,20.8,124.5,22,51.6,,,,,6,,6.0% +S371L,1.6,,17.1,,3.9,,18.4,,1,,4,,9.7,,2.2,,1.1,17.1,17,15,,,,,2,,17% +D405E,,,,0.186,,,,,,,,,,,,,,,,,,,,,,,0.0006% +D405N,1.8,,20.9,0.275,10.9,,1.9,,1,,2.1,,0.7,,0.5,,1,2,1.6,2.1,,,,,1,1,6.0% +E406D,,,,,51,,,,,,,,,,,,,,,,,,,,,,0.001% +K417E,,,,0.99,165.4,0.564,0.9,,0.4,,,,0.9,,1.3,,,,,,,,,,,9,0.0004% +K417H,,,,0.987,,0.34,,,,,,,,,,,,,,,,,,,,,0.0002% +K417I,,,,0.999,,,,,,,,,,,,,,,,,,,,,1,,0.0002% +K417M,,,,0.966,,,,,,,,,,,,,,,,,,,,,,,0.0003% +K417N,0.6,,381.7,0.997,12.5,,0.7,,0.7,,0.4,,0.7,,0.7,,0.6,1.7,0.5,0.9,0.3,,0.8,,3,6,23% +K417R,,,,0.115,61,,,,,,,,,,,,,,,,,,,,,2,0.004% +K417S,,,,0.98,,,,,,,,,,,,,,,,,,,,,,,0.0002% +K417T,,,49,0.987,7.1,,1.1,,,,,,0.7,,0.7,,0.7,0.9,0.6,,,,,,3,1,1.4% +D420A,,,,0.987,,,,,,,,,,,,,,,,,,,,,,,0.0002% +D420N,2.6,,60.6,0.993,,,,,,,,,,,0.7,,,,,,,,,,,1,0.0008% +N439K,2.4,,0.4,,0.8,,28.8,,1.2,,,,1,,0.5,,,1,0.9,,238.6,,0.8,,,2,0.6% +N440D,,,,,,,,0.473,,,,,1.3,,1.9,,,,,,,,,,1,2,0.0004% +N440E,,,,,,,,0.632,,,,,0.8,,,,,,,,,,,,,,0.0001% +N440I,,,,,,,,0.918,,,,,1.2,,,,,,,,,0.424,,,,,0.0006% +N440K,1.2,,1.1,,1,,92,0.565,1.3,,1,,1.5,,0.8,,0.3,2.1,1.6,1.8,647.1,0.815,1.1,,3,2,23% +N440R,,,,,,,,,,,,,,,,,,,,,,0.23,,,,,0.0002% +N440T,,,,,,,,0.496,,,,,0.8,,,,,,,,,,,,,,0.001% +N440Y,,,,,,,,0.504,,,,,0.7,,,,,,,,,,,,,,0.004% +S443Y,,,,,,,,0.821,,0.194,,,,,,,,,,,,0.585,,,,,0.0001% +K444E,,,,,,,,0.962,291.2,0.946,,,,,,0.81,,,,,,0.627,,,,8,0.0002% +K444F,,,,,,,,0.958,,0.883,,,,,,0.678,,,,,,0.672,,,,,0.0001% +K444I,,,,,,,,0.994,,0.982,,,,,,0.678,,,,,,0.641,,,,,0.0002% +K444L,,,,,,,153,0.971,,0.988,,,,,,0.69,,,,,,0.624,,,,,0.0001% +K444M,,,,,,,1577,0.969,,0.979,,,,,,,,,,,,0.208,,,,1,0.002% +K444N,,,,,,,755,0.943,,0.933,,,,,1901,0.718,,,,,33.7,,1.1,,,7,0.01% +K444R,,,,,,,,,200,0.964,,,,,,,,,,,1.1,,1.2,,,5,0.01% +K444T,,,,,2,,1026.6,0.982,,0.956,,,,,1814,0.635,,,,,44.3,,2,,5,4,0.002% +V445A,,,,,1.8,,548,0.98,35.5,,,,3.4,,83.3,,,,,,,,,,2,5,0.005% +V445D,,,,,,,,0.957,,0.564,,,,,,0.764,,,,,,,,,,1,0.0001% +V445F,,,,,,,,0.885,,,,,,,369,0.654,,,,,,,,,1,1,0.003% +V445I,,,,,,,,,,,,,,,,,,,,,5.6,,1.5,,,,0.003% +V445L,,,,,,,,0.806,,,,,,,,,,,,,7.2,,1.1,,,,0.0002% +G446A,,,,,,,,0.745,,,,,,,,,,,,,,,,,,,0.001% +G446D,,,,,,,,0.978,,,,,,,69,,,,,,,,,,8,4,0.001% +G446I,,,,,,,,0.953,,,,,,,,,,,,,,0.164,,,,1,0.0001% +G446N,,,,,,,,0.924,,,,,,,,,,,,,,,,,,,0.0008% +G446R,,,,,,,,0.953,,,,,,,7,,,,,,,,,,,1,0.002% +G446S,1.2,,0.9,,1.3,,574,0.824,3.7,,1.2,,1.6,,2,,1.1,0.9,1.3,3.4,3.5,,1.1,,1,,17% +G446T,,,,,,,,0.986,,,,,,,,,,,,,,,,,,,0.0002% +G446V,,,0.8,,0.7,,348.5,0.959,3.6,,,,1.5,,4.3,,,0.9,,,858,0.16,1.3,,4,4,0.1% +G447C,,,,,,,,0.591,,,,,,,,,,,,,,,,,,,0.0002% +G447D,,,,,,,,0.986,,0.935,,,,,,,,,,,,,,,,,0.0002% +G447F,,,,,,,,0.908,,0.863,,,,,,,,,,,,,,,,,0.0001% +G447S,,,,,,,,0.652,,0.171,,,,,,,,,,,,,,,,2,0.0007% +G447V,,,,,,,,0.841,,0.882,,,,,,,,,,,,,,,,,0.001% +N448D,,,,,,,,0.613,,0.859,,,,,,,,,,,,,,,,1,0.0005% +N448K,,,,,,,,0.691,,0.97,,,,,,,,,,,,0.47,,,,1,0.0006% +N448T,,,,,,,,0.126,,0.854,,,,,,,,,,,,,,,,,0.0006% +N448Y,,,,,,,,,,0.841,,,,,,,,,,,,0.672,,,,,0.0001% +Y449D,,,,,,,,,,0.674,,,,,,,,,,,,,,,,,0.0007% +N450D,,,,,1.4,,20.9,,382.3,0.7,,,,,,,,,,,,,,,1,5,0.002% +N450K,,,0.4,,,,,,9.1,,,,0.8,,0.7,,,,,,,,,,,2,0.03% +L452M,1,,0.9,,0.4,,1,,1,,0.5,,2.1,,0.6,,,0.9,8.1,1.3,,,,,,,0.03% +L452Q,3,,1.8,,3.1,,4.2,,2.2,,0.5,,2.7,,0.8,,,1.3,21.3,1.3,,,,,,,0.1% +L452R,1254.5,0.934,1,,1.1,,1.7,,5.7,,0.5,,1.1,,0.6,,35,1.3,116,1.1,,,,,4,6,38% +L452W,,0.179,,,,,,,,,,,,,,,,,,,,,,,,,0.002% +Y453F,1.4,,1.4,,456,0.574,1.3,,0.8,,,,1.1,,0.7,,,1.1,1.3,,,,1.1,,2,3,0.03% +Y453H,,,,,,0.427,,,,,,,,,,,,,,,,,,,,,0.0003% +L455F,,,,,80,0.364,1.1,,0.6,,3.6,,0.6,,,,,,,,1.7,,68.3,0.802,3,2,0.03% +L455M,,,,,,,,,,,,,,0.108,,,,,,,,,,,,,0.0002% +L455S,,,,,,0.545,,,,,,,,,,,,,,,,,,0.941,1,,0.002% +L455W,,,,0.966,,0.578,,,,,,,,,,,,,,,,,,0.973,2,,0.0001% +F456C,,,,0.987,,,,,,,,,,,,,,,,,,,,0.994,,,0.0002% +F456L,,,,,,,,,,,,,,,,,,,,,,,,0.946,2,1,0.005% +F456V,,,,0.969,,,,,,,,,,,,,,,,,0.2,,159.9,0.952,,3,0.0004% +S459P,,,,0.685,,,,,,,,,,,,,,,,,,,,,,,0.0004% +N460D,,,,0.105,,,,,,,,,,,,,,,,,,,,,,,0.0008% +N460H,,,,0.975,,,,,,,,,,,,,,,,,,,,,,1,0.0001% +N460I,,,,0.995,,,,,,,,,,,,,,,,,,,,,,,0.001% +N460K,1.5,,76.3,0.996,1.3,,1.3,,0.8,,1,,1.2,,1.2,,,8.9,2.4,,,,,,2,1,0.002% +N460S,0.5,,155.3,0.957,,,,,,,,,,,0.7,,,,,,,,,,,1,0.01% +N460T,2.3,,75,0.992,,,,,,,,,0.6,,,,,,,,,,,,,1,0.0003% +N460Y,1.7,,100,0.886,,,,,,,,,,,,,,,,,,,,,1,1,0.001% +A475D,,,,0.964,,0.381,,,,,,0.929,,,,,,,,,0.5,,1.2,,,1,0.0001% +A475V,,,16.7,0.611,,,,,0.6,,,,2.3,,,,,70.8,,,1.3,,1.2,,2,,0.03% +G476D,,,,,,0.895,,,,,,0.987,,,,,,,,,,,,,1,7,0.0007% +G476R,,,,0.733,,0.469,,,,,,0.973,,,,,,,,,,,,,,,0.0001% +G476T,,,,0.967,,,,,,,,0.929,,,,,,,,,,,,,,,0.0001% +V483A,39.6,,1,,0.4,,0.6,,,,,,,,0.3,,,1.5,,,1,,1,,8,,0.005% +E484A,678.6,0.911,3.4,,9,,1.5,,1.3,,8.1,,0.9,,1.4,,1.1,7.7,1.9,3.6,1.8,,1743.2,0.973,6,5,23% +E484D,100,0.889,,,,,,,,,7.1,,,,1,,,,,,1,,181.7,0.817,1,5,0.003% +E484G,,,,,,,,,,,,,,,,,,,,,,,137.3,0.937,2,3,0.003% +E484K,1333.3,0.97,2.9,,18.4,,1,,1,,8.1,,0.4,,0.7,,8.7,1.4,2.5,,0.4,,1388,0.966,30,33,2.9% +E484P,,0.993,,,,,,,,,,,,,,,,,,,,,,0.992,,,0.0008% +E484Q,100,0.987,1.3,,19,,1,,,,3,,0.4,,0.7,,,1.5,2.6,,1.4,,1743.2,0.991,11,1,0.2% +E484R,,0.991,,,,,,,,,,,,,,,,,,,,,,0.953,,,0.0005% +E484S,,0.702,,,,,,,,,,,,,,,,,,,,,,0.97,,,0.0008% +E484T,,0.954,,,,,,,,,,,,,,,,,,,,,,0.997,,,0.0007% +E484V,,0.977,,,,0.555,,,,,,,,,,,,,,,,,,0.983,2,2,0.01% +G485D,,0.75,,,4.4,,0.6,,,,,0.673,,,,,,,,,,,,,,3,0.001% +G485R,,0.885,,,,,,,,,,,,,,,,,,,,,0.7,,2,,0.001% +F486D,,,,,,0.983,,,,,,0.996,,,,,,,,,,,,,,,0.0002% +F486I,,0.803,,,,0.825,,,,,,0.149,,,1.7,,,,,,,,,,2,1,0.001% +F486L,,0.86,7.6,,61,0.267,0.8,,,,,,1.4,,,,,3.1,2.1,,,,1.1,,,2,0.002% +F486N,,,,0.163,,0.968,,,,,,0.985,,,,,,,,,,,,,,,0.0001% +F486P,,0.878,,0.316,,0.965,,,,,,0.985,,,,,,,,,,,,0.283,,1,0.0002% +F486S,,,,0.249,509.9,0.97,0.4,,,,600,0.997,,,,,,,,,,,,0.39,3,6,0.003% +F486T,,0.804,,0.157,,0.963,,,,,,0.987,,,,,,,,,,,,,,,0.0002% +F486V,490.3,0.73,11.3,0.142,814.9,0.945,0.9,,0.7,,135.5,0.285,1.1,,1.5,,,12.8,1.6,1.3,,,,,1,9,0.0007% +N487D,,,,0.952,,0.819,,,,,,0.939,,,,,,,,,,,,0.448,,3,0.0002% +N487H,,,,0.949,,,,,,,,0.41,,,,,,,,,,,,,,,0.0002% +N487S,,,,0.994,,,,,,,,0.471,,,,,,,,,,,,,,1,0.0002% +Y489H,,,,0.991,,0.943,,,,,,0.42,1.5,,2,,,,,,,,20.2,0.813,1,,0.001% +Y489W,,,,0.913,,0.738,,,,,,0.955,,,,,,,,,,,,,,,0.0002% +F490G,,0.908,,,,,,,,,,,,,,,,,,,,,,0.968,,,0.0001% +F490I,,,,,,,,,,,,,,,,,,,,,,,,0.981,,,0.0007% +F490L,844.3,,2.1,,2.9,,0.8,,,,,,,,1,,,0.7,,,2.1,,233.4,0.967,4,4,0.02% +F490R,,0.985,,,,,,,,,,,,,,,,,,,,,,0.993,,,0.002% +F490S,333.3,0.858,1.1,,0.8,,1.2,,1.1,,,,0.8,,1.7,,,1.3,134.9,,1.2,,4.1,,7,5,0.2% +F490V,,,,,,,,,,,,,,,,,,,,,,,,0.882,,2,0.003% +F490Y,,0.15,,,,,,,,,,,,,,,,,,,,,,,1,,0.002% +Q493D,,,,,,0.795,,,,,,,,,,,,,,,,,,0.866,,,0.0002% +Q493E,,,,,446,0.72,,,,,,,,,,,,,,,,,,,1,,0.009% +Q493H,13.9,,1,,,0.195,,,,,,,,,,,,,,,,,,,,,0.001% +Q493K,2451.3,0.983,54.2,0.378,301,0.633,1.4,,1.6,,1.9,,1.6,,1,,,,,,1.4,,3349,0.996,8,8,0.002% +Q493L,9.9,,3.8,,,0.179,,,,,,,1.1,,,,,,,,2,,20.5,0.72,1,,0.003% +Q493R,1185,0.965,46.4,0.582,42,0.112,1.5,,1.1,,6.5,,1.2,,1,,949,11.6,2,1.4,1,,917.3,0.981,17,6,23% +Q493V,,0.137,,0.131,,,,,,,,,,,,,,,,,,,,0.861,,,0.0002% +S494P,100,0.881,0.6,,2.1,,1.5,,1.2,,,,2,,0.7,,,0.7,1.6,,0.8,,99.1,0.905,12,3,0.2% +S494R,844.3,0.981,3.1,,1.1,,3,,,0.881,,,,,1.5,,,,,,,,,,,,0.0001% +G496S,1.1,,1.3,,1,,5.5,,1.8,,0.9,,1.1,,1.7,,0.6,2.5,1.2,2.2,,,,,,,17% +Q498H,,,,,,,17,,,,,,,,,,,,,,,,,,,,0.0004% +P499H,,,,,,,,0.334,,,,,,,1606,0.644,,,,,,,,,,2,0.001% +P499R,,,,,,,,0.892,,,,,,,976.7,0.668,,,,,,,,,,2,0.008% +P499S,,,,,,,206,0.813,,,,,,,37.5,,,,,,,,,,,,0.003% +P499T,,,,,,,,0.606,,,,,,,,,,,,,,,,,,,0.0007% +N501T,1.1,,10,,,,,,,,,,,,,,,,,,,,,,9,1,0.08% +N501Y,1.1,,5.3,,1,,1,,1.3,,1.5,,1.6,,0.7,,3.8,1,2.3,3.1,1.4,,1.5,,8,3,45% +G504C,,,,0.791,,,,,,,,,,,,,,,,,,,,,,,0.0001% +G504D,,,,0.237,,,,,,,,,,,,,,,,,,,1.8,,1,6,0.002% +G504I,,,,0.908,,,,,,,,,,,,,,,,,,,,,,,0.0002% +G504L,,,,0.684,,,,,,,,,,,,,,,,,,,,,,,0.0002% +G504N,,,,0.295,,,,,,,,,,,,,,,,,,,,,,,0.0006% +G504R,,,,0.281,,,,,,,,,,,,,,,,,,,,,,,0.0001% +G504V,,,,0.705,,,,,,,,,,,,,,,,,,,,,,,0.0006% +P507A,,,,,,,,0.361,,,,,,,,,,,,,,,,,,,0.0005% +N856K,1.4,,9.2,,2.1,,1.4,,1.3,,2.9,,1.7,,1.3,,1.3,1.6,2.3,1.7,,,,,,,18% +N969K,1.5,,5.7,,1.4,,1.6,,1.4,,2.4,,1.5,,3.9,,0.9,3.1,1.4,1.9,,,,,,,24% +E990A,,,,,,,,,,,6.1,,,,,,,,,,,,,,,,0.0004% +T1009I,,,,,,,,,,,8.2,,,,,,,,,,,,,,,,0.01% \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 8726bd1..2c0a694 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ s3fs st-files-connection seaborn matplotlib -pillow \ No newline at end of file +pillow +aiohttp \ No newline at end of file diff --git a/resistance_mut.py b/resistance_mut.py new file mode 100644 index 0000000..c0778fd --- /dev/null +++ b/resistance_mut.py @@ -0,0 +1,156 @@ +import json +from matplotlib import pyplot as plt +import numpy as np +import streamlit as st +import requests +import yaml +import pandas as pd +import logging +import aiohttp +import asyncio +import seaborn as sns + + +# Load configuration from config.yaml +with open('config.yaml', 'r') as file: + config = yaml.safe_load(file) + +server_ip = config.get('server', {}).get('ip_address', 'http://default_ip:8000') + +async def fetch_data(session, mutation, date_range): + payload = { + "aminoAcidMutations": [mutation], + "dateFrom": date_range[0].strftime('%Y-%m-%d'), + "dateTo": date_range[1].strftime('%Y-%m-%d'), + "fields": ["date"] + } + + async with session.post( + 'https://lapis.cov-spectrum.org/open/v2/sample/aggregated', + headers={ + 'accept': 'application/json', + 'Content-Type': 'application/json' + }, + json=payload + ) as response: + if response.status == 200: + data = await response.json() + return {"mutation": mutation, + "data": data.get('data', [])} + else: + logging.error(f"Failed to fetch data for mutation {mutation}.") + logging.error(f"Status code: {response.status}") + logging.error(await response.text()) + return {"mutation": mutation, + "data": None} + +async def fetch_all_data(mutations, date_range): + async with aiohttp.ClientSession() as session: + tasks = [fetch_data(session, mutation, date_range) for mutation in mutations] + return await asyncio.gather(*tasks) + +def fetch_reformat_data(formatted_mutations, date_range): + all_data = asyncio.run(fetch_all_data(formatted_mutations, date_range)) + + # get dates from date_range + dates = pd.date_range(date_range[0], date_range[1]).strftime('%Y-%m-%d') + + # get all unique dates + # dates = set() + # for data in all_data: + # if data['data']: + # for d in data['data']: + # dates.add(d['date']) + + + # make a dataframe with the dates as columns and the mutations as rows + df = pd.DataFrame(index=formatted_mutations, columns=list(dates)) + + # fill the dataframe with the data + for data in all_data: + if data['data']: + for d in data['data']: + df.at[data['mutation'], d['date']] = d['count'] + + return df + + +def plot_heatmap(df): + # Replace None with np.nan and remove commas from numbers + df = df.replace({None: np.nan, ',': ''}, regex=True).astype(float) + + # Create a colormap with a custom color for NaN values + cmap = sns.color_palette("Blues", as_cmap=True) + cmap.set_bad(color='#FFCCCC') # Set NaN values to a fainter red color + + # Adjust the plot size based on the number of rows in the dataframe + height = max(8, len(df) * 0.3) # Minimum height of 8, with 0.5 units per row + fig, ax = plt.subplots(figsize=(15, height)) + + annot = True if df.shape[0] * df.shape[1] <= 100 else False # Annotate only if the plot is small enough + sns.heatmap(df, cmap=cmap, ax=ax, cbar_kws={'label': 'Occurrence Frequency', 'orientation': 'horizontal'}, + linewidths=.5, linecolor='lightgrey', annot=annot, fmt=".1f", + annot_kws={"size": 10}, mask=df.isnull(), cbar=True, cbar_ax=fig.add_axes([0.15, 0.90, 0.7, 0.02])) + + # Set axis labels + ax.set_xticks([0, len(df.columns) // 2, len(df.columns) - 1]) + ax.set_xticklabels([df.columns[0], df.columns[len(df.columns) // 2], df.columns[-1]], rotation=45) + return fig + + + +def app(): + st.title("Resistance Mutations") + + st.write("This page allows you to visualize the numer of observed resistance mutations over time.") + st.write("The data is fetched from the COV-Spectrum API and currently used clinical data.") + + st.write("The sets of resistance mutations are provide from Stanfords Coronavirus Antivirial & Reistance Database. Last updated 05//14/2024") + + st.write("This is a demo frontend to later make the first queries to SILO for wastewater data.") + + # make a horizontal line + st.markdown("---") + + st.write("Select from the following resistance mutation sets:") + + # TODO: currently hardcoded, should be fetched from the server + options = { + "3CLpro Inhibitors": 'data/3CLpro_inhibitors_datasheet.csv', + "RdRP Inhibitors": 'data/RdRP_inhibitors_datasheet.csv', + "Spike mAbs": 'data/spike_mAbs_datasheet.csv' + } + + selected_option = st.selectbox("Select a resistance mutation set:", options.keys()) + + df = pd.read_csv(options[selected_option]) + + # Get the list of mutations for the selected set + mutations = df['Mutation'].tolist() + # Lambda function to format the mutation list, from S24L to S:24L + format_mutation = lambda x: f"{x[0]}:{x[1:]}" + # Apply the lambda function to each element in the mutations list + formatted_mutations = [format_mutation(mutation) for mutation in mutations] + + st.write(f"Selected mutations:") + st.write(formatted_mutations) + + + # Allow the user to choose a date range + st.write("Select a date range:") + date_range = st.date_input("Select a date range:", [pd.to_datetime("2022-01-01"), pd.to_datetime("2024-01-01")]) + + if st.button("Fetch Data"): + st.write("Fetching data...") + df = fetch_reformat_data(formatted_mutations, date_range) + + # Check if the dataframe is all NaN + if df.isnull().all().all(): + st.error("The fetched data contains only NaN values. Please try a different date range or mutation set.") + else: + # Plot the heatmap + fig = plot_heatmap(df) + st.pyplot(fig) + +if __name__ == "__main__": + app() \ No newline at end of file diff --git a/resistance_mut_silo.py b/resistance_mut_silo.py new file mode 100644 index 0000000..aab2bd6 --- /dev/null +++ b/resistance_mut_silo.py @@ -0,0 +1,166 @@ +import json +from matplotlib import pyplot as plt +import numpy as np +import streamlit as st +import requests +import yaml +import pandas as pd +import logging +import aiohttp +import asyncio +import seaborn as sns + + +# Load configuration from config.yaml +with open('config.yaml', 'r') as file: + config = yaml.safe_load(file) + +server_ip = config.get('server', {}).get('lapis_address', 'http://default_ip:8000') + +async def fetch_data(session, mutation, date_range): + payload = { + "aminoAcidMutations": [mutation], + "sampling_dateFrom": date_range[0].strftime('%Y-%m-%d'), + "sampling_dateTo": date_range[1].strftime('%Y-%m-%d'), + "fields": ["sampling_date"] + } + + async with session.post( + f'{server_ip}/sample/aggregated', + headers={ + 'accept': 'application/json', + 'Content-Type': 'application/json' + }, + json=payload + ) as response: + if response.status == 200: + data = await response.json() + return {"mutation": mutation, + "data": data.get('data', [])} + else: + logging.error(f"Failed to fetch data for mutation {mutation}.") + logging.error(f"Status code: {response.status}") + logging.error(await response.text()) + return {"mutation": mutation, + "data": None} + +async def fetch_all_data(mutations, date_range): + async with aiohttp.ClientSession() as session: + tasks = [fetch_data(session, mutation, date_range) for mutation in mutations] + return await asyncio.gather(*tasks) + +def fetch_reformat_data(formatted_mutations, date_range): + all_data = asyncio.run(fetch_all_data(formatted_mutations, date_range)) + + # get dates from date_range + dates = pd.date_range(date_range[0], date_range[1]).strftime('%Y-%m-%d') + + # get all unique dates + # dates = set() + # for data in all_data: + # if data['data']: + # for d in data['data']: + # dates.add(d['date']) + + + # make a dataframe with the dates as columns and the mutations as rows + df = pd.DataFrame(index=formatted_mutations, columns=list(dates)) + + # fill the dataframe with the data + for data in all_data: + if data['data']: + for d in data['data']: + df.at[data['mutation'], d['sampling_date']] = d['count'] + + return df + + +def plot_heatmap(df): + # Replace None with np.nan and remove commas from numbers + df = df.replace({None: np.nan, ',': ''}, regex=True).astype(float) + + # Create a colormap with a custom color for NaN values + cmap = sns.color_palette("Blues", as_cmap=True) + cmap.set_bad(color='#FFCCCC') # Set NaN values to a fainter red color + + # Adjust the plot size based on the number of rows in the dataframe + height = max(8, len(df) * 0.3) # Minimum height of 8, with 0.5 units per row + fig, ax = plt.subplots(figsize=(15, height)) + + annot = True if df.shape[0] * df.shape[1] <= 100 else False # Annotate only if the plot is small enough + sns.heatmap(df, cmap=cmap, ax=ax, cbar_kws={'label': 'Occurrence Frequency', 'orientation': 'horizontal'}, + linewidths=.5, linecolor='lightgrey', annot=annot, fmt=".1f", + annot_kws={"size": 10}, mask=df.isnull(), cbar=True, cbar_ax=fig.add_axes([0.15, 0.90, 0.7, 0.02])) + + # Set axis labels + ax.set_xticks([0, len(df.columns) // 2, len(df.columns) - 1]) + ax.set_xticklabels([df.columns[0], df.columns[len(df.columns) // 2], df.columns[-1]], rotation=45) + return fig + + + +def app(): + st.title("Resistance Mutations from Wastewater Data") + + st.write("This page allows you to visualize the numer of observed resistance mutations over time.") + st.write("The data is fetched from the WISE-CovSpectrum API and currently cointains demo data for Sep-Oct 2024.") + + st.write("The sets of resistance mutations are provide from Stanfords Coronavirus Antivirial & Reistance Database. Last updated 05/14/2024") + + st.write("This is a demo frontend to later make the first queries to SILO for wastewater data.") + + # make a horizontal line + st.markdown("---") + + st.write("Select from the following resistance mutation sets:") + + # TODO: currently hardcoded, should be fetched from the server + options = { + "3CLpro Inhibitors": 'data/3CLpro_inhibitors_datasheet.csv', + "RdRP Inhibitors": 'data/RdRP_inhibitors_datasheet.csv', + "Spike mAbs": 'data/spike_mAbs_datasheet.csv' + } + + selected_option = st.selectbox("Select a resistance mutation set:", options.keys()) + + df = pd.read_csv(options[selected_option]) + + gene_name = { + "3CLpro Inhibitors": "ORF1a", + "RdRP Inhibitors": "ORF1b", + "Spike mAbs": "S" + } + + # get the gene name + gene = gene_name[selected_option] + + # Get the list of mutations for the selected set + mutations = df['Mutation'].tolist() + # Lambda function to format the mutation list, from S24L to S:24L + format_mutation = lambda x: f"{gene}:{x[0]}{x[1:]}" + #format_mutation = lambda x: f"{x[0]}:{x[1:]}" + # Apply the lambda function to each element in the mutations list + formatted_mutations = [format_mutation(mutation) for mutation in mutations] + + st.write(f"Selected mutations:") + st.write(formatted_mutations) + + + # Allow the user to choose a date range + st.write("Select a date range:") + date_range = st.date_input("Select a date range:", [pd.to_datetime("2024-09-30"), pd.to_datetime("2024-10-16")]) + + if st.button("Fetch Data"): + st.write("Fetching data...") + df = fetch_reformat_data(formatted_mutations, date_range) + + # Check if the dataframe is all NaN + if df.isnull().all().all(): + st.error("The fetched data contains only NaN values. Please try a different date range or mutation set.") + else: + # Plot the heatmap + fig = plot_heatmap(df) + st.pyplot(fig) + +if __name__ == "__main__": + app() \ No newline at end of file