import streamlit as st import pandas as pd from utils import call_subprocess def insert_arrow(): return '' def insert_chart_icon(choice=0): if choice == 0: return '' else: return '' def insert_edit_icon(): return '' def insert_generate_icon(): return '' @st.cache_resource def get_cvms_version(): return ( str( call_subprocess( f"Rscript cvms_version.R", message="cvms versioning script", return_output=True, encoding="UTF-8", ) ) .split("[1]")[-1] .replace("‘", "") .replace("’", "") ) @st.cache_data def get_example_counts(): return pd.DataFrame( { "Target": ["cl1", "cl2", "cl1", "cl2"], "Prediction": ["cl1", "cl2", "cl2", "cl1"], "Sub*": [ "(57/60)", "(46/50)", "(12/15)", "(23/25)", ], "N": [12, 10, 3, 5], } ) @st.cache_data def get_example_data(): return pd.DataFrame( { "Target": ["cl1", "cl1", "cl2", "cl2", "cl1", "cl1"], "Prediction": ["cl1", "cl2", "cl2", "cl1", "cl1", "cl2"], } ) def intro_text(): col1, col2 = st.columns([8, 2]) with col1: st.title("Plot Confusion Matrix") st.markdown( "A confusion matrix plot is a great tool for inspecting your " "machine learning model's performance on a classification task. " "This application enables you to plot a confusion matrix on your own data, " "**without a single line of code**. \n\n" "It's designed for high flexibility AND quick results with " "templates and good default settings.\n\n" ) with col2: st.image( "https://github.com/LudvigOlsen/cvms/raw/master/man/figures/cvms_logo_242x280_250dpi.png", width=125, ) st.markdown("""---""") col1, col2 = st.columns(2) with col1: st.subheader("Have your data ready?") st.markdown( # TODO: Make A,B, etc. icons "Upload a csv file with either: \n\n" f"{insert_chart_icon(1)} **Targets** and **predictions** \n\n" f"{insert_chart_icon(0)} Existing confusion matrix **counts** \n\n" f"{insert_arrow()} Specify the columns to use\n\n" f"{insert_arrow()} Press **Generate plot**\n\n", unsafe_allow_html=True, ) with col2: st.subheader("No data to upload?") st.markdown( "No worries! Either: \n\n" f"{insert_edit_icon()} **Input** your counts directly! \n\n" f"{insert_generate_icon()} **Generate** some data with **very** easy controls! \n\n" f"{insert_arrow()} Press **Generate plot**\n\n", unsafe_allow_html=True, ) st.markdown("""---""") st.markdown( "This release is an **alpha** version (very early). Report errors or suggestions " "on [GitHub](https://github.com/LudvigOlsen/cvms_plot_app/issues)." ) st.write( "The plot is created with the [**cvms**](https://github.com/LudvigOlsen/cvms) R package " f"(v/{get_cvms_version()}, LR Olsen & HB Zachariae, 2019)." ) # TODO Add citation stuff st.markdown( '

' "DATA PRIVACY: For technical reasons, the uploaded data is temporarily stored " "on the server. While we, the authors, won't access your data, we make " "*no guarantees* about the privacy of your data (not our servers). " "Please do not upload sensitive data. The application " "only requires either predictions and targets or counts. " "

", unsafe_allow_html=True, ) def generate_data_text(): st.subheader("Generate data") st.write( "Quickly try the application by generating a dataset with targets and predictions. " "Select a number of classes and observations, and you're ready to go! " ) def enter_count_data_text(): st.subheader("Enter counts") st.write( "If you already have the confusion matrix counts and want to plot them. " "Enter the counts and get designing! " ) st.write("Start by entering the names of your classes:") def upload_counts_text(): st.subheader("Upload your counts") st.write( "Plot an existing confusion matrix (counts of target-prediction combinations). " ) col1, col2 = st.columns([5, 4]) with col1: st.markdown( "The application expects a `.csv` file with: \n" "1) A `target classes` column. \n\n" "2) A `predicted classes` column. \n\n" "3) A `combination count` column for the " "combination frequency of 1 and 2. \n\n" "4) (\\***Optionally**) a `sub` column with text " "that replaces the bottom text in the middle of tiles. \n\n" "Other columns are currently ignored. " "In the next step, you will be asked to select the names of these two columns. " ) with col2: st.write("Example of such a file:") st.dataframe(get_example_counts(), hide_index=True) def upload_predictions_text(): st.subheader("Upload your predictions") col1, col2 = st.columns([5, 4]) with col1: st.markdown( "The application expects a `.csv` file with: \n" "1) A `target` column. \n" "2) A `prediction` column. \n" "Predictions should be class predictions (not probabilities). \n\n" "Other columns are currently ignored. \n\n" "In the next step, you will be asked to select the names of these two columns. " ) with col2: st.write("Example of such a file:") st.dataframe(get_example_data(), hide_index=True) def columns_text(): st.subheader("Specify columns") st.write( "Please select which of the columns in the data should be used for targets and predictions." ) def design_text(): st.subheader("Design your plot") st.write("This is where you customize the design of your confusion matrix plot.") st.markdown( "We suggest you go directly to `Generate plot` to see the starting point. Then go back and tweak to your liking! " "You can also select one of the templates or upload previously saved design settings." ) st.markdown( "The *width* and *height* settings are usually necessary to adjust as they " "change the relative size of the elements. Try adjusting 100px at a " "time for a start." ) st.write("Get designing!") st.write("")