# Project export: Cancer360°

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 10.0
- Tagline: Helping Cancer Patients with AI Nursing and Patient Care
- Devpost: https://devpost.com/software/cal-hacks-project
- GitHub: https://github.com/MarcusUniversee/Cancer360
- Demo: http://helpingcancerpatientswith.tech/
- Result: winner (Hack on AI; Most Creative Use of Reflex)
- Team: 4 GitHub contributor(s) — MarcusUniversee (32 commits), Timothy Gao (22 commits), yifantong1010 (7 commits), WebDeke (2 commits)

## Devpost submission (written by the team)

### Overview

For Evaluators/Sponsors Scroll down for a handy guide to navigating our repository and our project's assets. 💥 - How it all started Cancer is a disease that has affected our team quite directly. All of our team members know a relative or loved one that has endured or lost their life due to cancer. This makes us incredibly passionate about wanting to improve cancer patient care. We identi fied a common thread of roadblocks that our loved ones went through during their journey through their diagnosis/treatment/etc: Diagnosis and Staging: Properly diagnosing the type and stage of cancer is essential for determining the most appropriate treatment plan. Treatment Options: There are many different types of cancer, and treatment options can vary widely. Selecting the most effective and appropriate treatment for an individual patient can be challenging. Multidisciplinary Care: Coordinating care among various healthcare professionals, including oncologists, surgeons, radiologists, nurses, and others, can be complex but is necessary for comprehensive cancer care. Communication: Effective communication among patients, their families, and healthcare providers is crucial for making informed decisions and ensuring the patient's needs and preferences are met. 📖 -

### What it does

We built Cancer360° to create a novel, multimodal approach towards detecting and predicting lung cancer. We synthesized four modes of data qualitative (think demographics, patient history), image (of lung CT scans), text (collected by an interactive chatbot), and physicical (via the ZeppOS Smartwatch) with deep learning frameworks and large language models to copmute a holistic metric for patient likelihood of lung cancer. Through this data-driven approach, we aim to address what we view as "The BFSR": The 'Big Four' of Surmountable Roadblocks: Diagnosis: Our diagnosis system is truly multimodal through our 4 modes: quantitative (uses risk factors, family history, demographics), qualitative (analysis of medical records like CT Scans), physical measurements (through our Zepp OS App), and our AI Nurse. Treatment Options: Our nurse can suggest multiple roadmaps of treatment options that patients could consider. For accessibility and ease of understanding, we created an equivalent to Google's featured snippets when our nurse mentions treatment options or types of treatment. Multidisciplinary Care: The way Cancer360° has been built is to be a digital aid that bridges the gaps with the automated and manual aspects of cancer treatment. Our system prompts patients to enter relevant information for our nurse to analyze and distribute what's important to healthcare professionals. Communication: This is a major need for patients and families in the road to recovery. Cancer360's AI nurse accomplishes this through our emotionally-sensitive responses and clear/instant communication with patients that input their information, vitals, and symptoms. 🔧 -

### How we built it

To build our Quantitative Mode, we used the following: numpy: for general math and numpy.array Pandas: for data processing, storage SKLearn: for machine learning (train_test_split, classification_report) XGBoost: Extreme Boosting Trees Decision Trees To build our Qualitative Mode, we used the following: OpenCV and PIL (Python Imaging Library): For Working With Image Data MatPlotLib and Seaborn : For Scientific Plotting Keras: Image Data Augmentation (think rotating and zooming in), Model Optimizations (Reduce Learning Rate On Plateau) Tensorflow: For the Convolutional Neural Network (CNN) To build our AI Nurse, we used the following: Together.ai: We built our chatbot with the Llama2 LLM API and used tree of thought prompt engineering to optimize our query responses To build the portal, we used the following: Reflex: We utilized the Reflex platform to build our entire frontend and backend, along with all interactive elements. We utilized front end components such as forms, buttons, progress bars, and more. More importantly, Reflex enabled us to directly integrate python-native applications like machine learning models from our quantitative and qualitative modes or our AI Nurse directly into the backend. 📒 - The Efficacy of our Models With Quantitative/Tabular Data: We collected quantitative data for patient demographic, risk factors, and history (in the form of text, numbers, and binary (boolean values)). We used a simple keyword search algorithm to identify risk keywords like “Smoking” and “Wheezing” to transform the text into quantitative data. Then we aggregated all data into a single Pandas dataframe and applied one-hot-encoding on categorical variables like gender. We then used SKLearn to create a 80-20 test split, and tested various models via the SKLearn library, including Logistic Regression, Random Forest, SVM, and K Nearest Neighbors. We found that ultimately, XGBoost performed best with the highest 98.39% accuracy within a reasonable 16-hour timeframe. Our training dataset was used in a research paper and can be accessed here. This high accuracy speaks to the reliability of our model. However, it's essential to remain vigilant against overfitting and conduct thorough validation to ensure its generalizability, a testament to our commitment to both performance and robustness. View our classification report here With Image Data: Our solution is well-equipped to handle complex medical imaging tasks. Using data from the Iraq-Oncology Teaching Hospital/National Center for Cancer Diseases (IQ-OTH/NCCD) lung cancer dataset, and deep learning frameworks from tensorflow and keras, we were able to build a convolution neural network to classify patient CT scans as malignant or benign. Our convolutional neural network was fine-tuned for binary image classification of 512x512 RGB images, with multiple convolutional, max-pooling, normalization, and dense layers, compiled using the Adam optimizer and binary crossentropy loss. We also used OpenCV, PIL, Matplotlib, and Numpy to deliver a commendable 93% accuracy over a 20-hour timeframe. The utilization of dedicated hardware resources, such as Intel developer cloud with TensorFlow GPU, accelerates processing by 24 times compared to standard hardware. While this signifies our technological edge, it's important to acknowledge that image classification accuracy can vary based on data quality and diversity, making the 93% accuracy an achievement that underscores our commitment to delivering high-quality results. Malignant CT Scan Benign CT Scan AI Nurse: The AI Nurse powered by Together.ai and LLMs (such as Llama2) introduces an innovative approach to patient interaction and risk factor determination. Generating "trees of thoughts" showcases our ability to harness large language models for effective communication. Combining multiple AI models to determine risk factor percentages for lung cancer demonstrates our holistic approach to healthcare support. However, it's essential to acknowledge that the efficacy of this solution is contingent on the quality of language understanding, data processing, and the integration of AI models, reflecting our dedication to continuous improvement and fine-tuning. 🚩 -

### Challenges we ran into

Challenges we fixed: Loading our neural network model into the Reflex backend. After using keras to save the model as a “.h5” extension, we were able to load and run the model locally on my jupyter notebook, however when we tried to load it in the Reflex backend, we kept getting a strange Adam optimizer build error. we tried everything: saving the model weights separately, using different file extensions like .keras, and even saving the model on as a .json file. Eventually, we realized that this was a known issue with m1/m2 macs and tensorflow Fixed the Get Started Button in Reflex header (Issue: button wouldn’t scale to match the text length) - Moved the button outside the inner hstack, but still the outer hstack Integrating together ai chatbot model into Reflex: A lot of our time was spent trying to get the integration working. Challenges we didn’t fix: Left aligning the AI response and right aligning the user input in the chatbot Fine tuning a second model to predict lung cancer rate from the chatbot responses from the first model - Could not get enough training data, too computationally taxing and few shot learning did not produce results Fixing bugs related to running a virtual javascript environment within Python via PyV8 Left aligning the AI response and right aligning the user input in the chatbot Fine tuning a second model to predict lung cancer rate from the chatbot responses from the first model - Could not get enough training data, too computationally taxing and few shot learning did not produce results Fixing bugs related to running a virtual javascript environment within Python via PyV8 🏆 -

### Accomplishments we're proud of

Going from idea generation to working prototype, with integration of 4 data modalities - Qualitative Mode, Quantitative Mode, and our AI Nurse, and Smartwatch Data, within the span of less than two days Integrating machine learning models and large language models within our application in a way that is directly accessible to users Learning a completely new web development framework (Reflex) from scratch without extensive documentation and ChatGPT knowledge Working seamlessly as a team and take advantage of the component-centered nature of Reflex to work independently and together 📝 -

### What we learned

Ameya: "I was fortunate enough to learn a lot about frameworks like Reflex and Together.ai." Marcus: "Using Reflex and learning its components to integrate backend and frontend seamlessly." Timothy: "I realized how I could leverage Reflex, Intel Developer Cloud, Together.ai, and Zepp Health to empower me in developing with cutting edge technologies like LLMs and deep learning models." Alex: "I learned a lot of front end development skills with Reflex that I otherwise wouldn’t have learned as a primarily back-end person." ✈️ -

### What's next

Just like how a great trip has a great itinenary, we envision Cancer360° future plans in phases. Phase 1: Solidifying our Roots Phase 1 involves the following goals: Revamping our user interface to be more in-line with our mockups Increasing connectivity with healthcare professionals Phase 2: Branching Out View the gallery to see this. Phase 2 involves the following goals: Creating a mobile app for iOS and Android of this service Furthering development of our models to detect and analyze other types of cancers and create branches of approaches depending on the cancer Completing our integration of the physical tracker on Zepp OS Phase 3: Big Leagues Phase 3 involves the following goals: Expanding accessibility of the app through having our services be available in numerous different languages Working with healthcare institutions to further improve the usability of the suite 📋 - Evaluator's Guide to Cancer360° Intended for judges, however the viewing public is welcome to take a look. Hey! We wanted to make this guide in order to help provide you further information on our implementations of certain programs and provide a more in-depth look to cater to both the viewing audience and evaluators like yourself. Sponsor Services We Have Used This Hackathon Reflex The founders (Nikhil and Alex) were not only eager to assist but also highly receptive to our feedback, contributing significantly to our project's success. In our project, we made extensive use of Reflex for various aspects: Project Organization and Hosting: We hosted our website on Reflex, utilizing their component-state filesystem for seamless project organization. Frontend: We relied on Reflex components to render everything visible on our website, encompassing graphics, buttons, forms, and more. Backend: Reflex states played a crucial role in our project by facilitating data storage and manipulation across our components. In this backend implementation, we seamlessly integrated our website features, including the chatbot, machine learning model, Zepp integration, and X-ray scan model. Together AI In our project, Together AI played a pivotal role in enhancing various aspects: Cloud Service: We harnessed the robust capabilities of Together AI's cloud services to host, run, and fine-tune llama 2, a Large Language Model developed by META, featuring an impressive 70 billion parameters. To ensure seamless testing, we evaluated more than ten different chat and language models from various companies. This was made possible thanks to Together AI's commitment to hosting over 30 models on a single platform. Cloud Service: We harnessed the robust capabilities of Together AI's cloud services to host, run, and fine-tune llama 2, a Large Language Model developed by META, featuring an impressive 70 billion parameters. To ensure seamless testing, we evaluated more than ten different chat and language models from various companies. This was made possible thanks to Together AI's commitment to hosting over 30 models on a single platform. Integration: We seamlessly integrated Together AI's feature set into our web app, combined with Reflex, to deliver a cohesive user experience. Integration: We seamlessly integrated Together AI's feature set into our web app, combined with Reflex, to deliver a cohesive user experience. Tuning: Leveraging Together AI's user-friendly hyperparameter control and prompt engineering, we optimized our AI nurse model for peak performance. As a result, our AI nurse consistently generated the desired outputs at an accelerated rate, surpassing default performance levels, all without the need for extensive tuning or prompt engineering. Tuning: Leveraging Together AI's user-friendly hyperparameter control and prompt engineering, we optimized our AI nurse model for peak performance. As a result, our AI nurse consistently generated the desired outputs at an accelerated rate, surpassing default performance levels, all without the need for extensive tuning or prompt engineering. Intel Developer Cloud Our project would not have been possible without the massive computing power of Intel cloud computers. For reference, here is the CNN training time on my local computer. And here is the CNN training time on my Intel® Xeon 4th Gen ® Scalable processor virtual compute environment and tensorflow GPU. A remarkable 20x Speedup! This huge leap in compute speed empowered by Intel® cloud computing enabled us to re-train our models with lightning speed as we worked to debugg and worked to integrate it into our backend. It also made fine-tuning our model much easier as we can tweak the hyperparameters and see their effects on model performance within the span of minutes. Zepp Health We utilized the ZeppOS API to query real-time user data for calories burned, fat burned, blood oxygen, and PAI (Personal Activity Index). We worked set up a PyV8 virtual javascript environment to run javascript code within Python to integrate the ZeppOS API into our application. Using collected data from the API, we used an ensemble algorithm to compute a health metric evaluating patient health, which ultimately feeds into our algorithm to find patient risk for lung cancer. GitHub We used GitHub for our project by creating a GitHub repository to host our hackathon project's code. We also ensured that our use of GitHub stood out with a detailed ReadMe page, meaningful pull requests, and a collaboration history, showcasing our dedication to improving cancer patient care through Cancer360°. We leveraged GitHub not only for code hosting but also as a platform to collaborate, push code, and receive feedback. .Tech Domains We harnessed the potential of a .tech domain to visually embody our vision for Cancer360°, taking a step beyond traditional domains. By registering the website helpingcancerpatientswith.tech, we not only conveyed our commitment to innovative technology but also made a memorable online statement that reflects our dedication to improving the lives of cancer patients.

## README (from the GitHub repository)

# Cancer360°

### Calhacks 10.0 Prize Winner: Hack on AI and Best use of Reflex

## 💥 - How it all started

Cancer is a disease that has affected our team quite directly. All of our team members know a relative or loved one that has endured or lost their life due to cancer. This makes us incredibly passionate about wanting to improve cancer patient care. We identi fied a common thread of roadblocks that our loved ones went through during their journey through their diagnosis/treatment/etc:

- **Diagnosis and Staging:** Properly diagnosing the type and stage of cancer is essential for determining the most appropriate treatment plan.
- **Treatment Options:** There are many different types of cancer, and treatment options can vary widely. Selecting the most effective and appropriate treatment for an individual patient can be challenging.
- **Multidisciplinary Care:** Coordinating care among various healthcare professionals, including oncologists, surgeons, radiologists, nurses, and others, can be complex but is necessary for comprehensive cancer care.
- **Communication:** Effective communication among patients, their families, and healthcare providers is crucial for making informed decisions and ensuring the patient's needs and preferences are met.

## 📖 - What it does

We built Cancer360° to create a novel, multimodal approach towards detecting and predicting lung cancer. We synthesized four modes of data qualitative (think demographics, patient history), image (of lung CT scans), text (collected by an interactive chatbot), and physicical (via the ZeppOS Smartwatch) with deep learning frameworks and large language models to copmute a holistic metric for patient likelihood of lung cancer. Through this data-driven approach, we aim to address what we view as "The BFSR": The 'Big Four' of Surmountable Roadblocks:

- **Diagnosis:** Our diagnosis system is truly multimodal through our 4 modes: quantitative (uses risk factors, family history, demographics), qualitative (analysis of medical records like CT Scans), physical measurements (through our Zepp OS App), and our AI Nurse.
- **Treatment Options:** Our nurse can suggest multiple roadmaps of treatment options that patients could consider. For accessibility and ease of understanding, we created an equivalent to Google's featured snippets when our nurse mentions treatment options or types of treatment.
- **Multidisciplinary Care:** The way Cancer360° has been built is to be a digital aid that bridges the gaps with the automated and manual aspects of cancer treatment. Our system prompts patients to enter relevant information for our nurse to analyze and distribute what's important to healthcare professionals.
- **Communication:** This is a major need for patients and families in the road to recovery. Cancer360's AI nurse accomplishes this through our emotionally-sensitive responses and clear/instant communication with patients that input their information, vitals, and symptoms.

## 🔧 - How we built it

To build our Quantitative Mode, we used the following:

- **numpy**: for general math and numpy.array
- **Pandas**: for data processing, storage
- **SKLearn**: for machine learning (train_test_split, classification_report)
- **XGBoost**: Extreme Boosting Trees Decision Trees

To build our Qualitative Mode, we used the following:

- **OpenCV** and **PIL** (Python Imaging Library): For Working With Image Data
- **MatPlotLib** and **Seaborn** : For Scientific Plotting
- **Keras**: Image Data Augmentation (think rotating and zooming in), Model Optimizations (Reduce Learning Rate On Plateau)
- **Tensorflow**: For the Convolutional Neural Network (CNN)

To build our AI Nurse, we used the following:

- **Together.ai:** We built our chatbot with the Llama2 LLM API and used tree of thought prompt engineering to optimize our query responses

To build the portal, we used the following:

- **Reflex:** We utilized the Reflex platform to build our entire frontend and backend, along with all interactive elements. We utilized front end components such as forms, buttons, progress bars, and more. More importantly, Reflex enabled us to directly integrate python-native applications like machine learning models from our quantitative and qualitative modes or our AI Nurse directly into the backend.

## 📒 - The Efficacy of our Models

**With Quantitative/Tabular Data:**

We collected quantitative data for patient demographic, risk factors, and history (in the form of text, numbers, and binary (boolean values)). We used a simple keyword search algorithm to identify risk keywords like “Smoking” and “Wheezing” to transform the text into quantitative data. Then we aggregated all data into a single Pandas dataframe and applied one-hot-encoding on categorical variables like gender. We then used SKLearn to create a 80-20 test split, and tested various models via the SKLearn library, including Logistic Regression, Random Forest, SVM, and K Nearest Neighbors. We found that ultimately, XGBoost performed best with the highest 98.39% accuracy within a reasonable 16-hour timeframe. Our training dataset was used in a research paper and can be accessed [here.](https://www.kaggle.com/datasets/nancyalaswad90/lung-cancer) This high accuracy speaks to the reliability of our model. However, it's essential to remain vigilant against overfitting and conduct thorough validation to ensure its generalizability, a testament to our commitment to both performance and robustness.

[View our classification report here](https://imgur.com/a/YAvXwyk)

**With Image Data:**
Our solution is well-equipped to handle complex medical imaging tasks. Using data from the Iraq-Oncology Teaching Hospital/National Center for Cancer Diseases (IQ-OTH/NCCD) lung cancer dataset, and deep learning frameworks from tensorflow and keras, we were able to build a convolution neural network to classify patient CT scans as malignant or benign. Our convolutional neural network was fine-tuned for binary image classification of 512x512 RGB images, with multiple convolutional, max-pooling, normalization, and dense layers, compiled using the Adam optimizer and binary crossentropy loss. We also used OpenCV, PIL, Matplotlib, and Numpy to deliver a commendable 93% accuracy over a 20-hour timeframe. The utilization of dedicated hardware resources, such as Intel developer cloud with TensorFlow GPU, accelerates processing by 24 times compared to standard hardware. While this signifies our technological edge, it's important to acknowledge that image classification accuracy can vary based on data quality and diversity, making the 93% accuracy an achievement that underscores our commitment to delivering high-quality results.

[Malignant CT Scan](https://imgur.com/a/8oGYz71)

[Benign CT Scan](https://imgur.com/a/3X3zb7k)

**AI Nurse:**
The AI Nurse powered by Together.ai and LLMs (such as Llama2) introduces an innovative approach to patient interaction and risk factor determination. Generating "trees of thoughts" showcases our ability to harness large language models for effective communication. Combining multiple AI models to determine risk factor percentages for lung cancer demonstrates our holistic approach to healthcare support. However, it's essential to acknowledge that the efficacy of this solution is contingent on the quality of language understanding, data processing, and the integration of AI models, reflecting our dedication to continuous improvement and fine-tuning.

## 🚩 - Challenges we ran into

- Challenges we fixed:
- Loading our neural network model into the Reflex backend. After using keras to save the model as a “.h5” extension, we were able to load and run the model locally on my jupyter notebook, however when we tried to load it in the Reflex backend, we kept getting a strange Adam optimizer build error. we tried everything: saving the model weights separately, using different file extensions like .keras, and even saving the model on as a .json file. Eventually, we realized tha

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 29 recognized source files, 66 KB.
- FastAPI (technology) — detected in the code
- Python (language) — detected in the code
- Redis (technology) — detected in the code
- TensorFlow (technology) — detected in the code

## Codebase structure (from repository index)

### Files (52 of 52)

```
.DS_Store
.gitignore
.ipynb_checkpoints/Image_prediction-checkpoint.ipynb
.ipynb_checkpoints/lung-cancer-risk-factors-checkpoint.ipynb
.ipynb_checkpoints/model-checkpoint.json
.ipynb_checkpoints/Risk_factor_prediction-checkpoint.ipynb
assets/.DS_Store
Cancer360/__init__.py
Cancer360/.DS_Store
Cancer360/Cancer360.py
Cancer360/chatbot.py
Cancer360/cnn_weights.h5
Cancer360/components/__init__.py
Cancer360/components/appointment.py
Cancer360/components/chatting.py
Cancer360/components/cnn_detect.py
Cancer360/components/FinalPage.py
Cancer360/components/header.py
Cancer360/components/sidebar.py
Cancer360/components/steps_sidebar.py
Cancer360/components/timmycomponent.py
Cancer360/components/zepp.py
Cancer360/pages/__init__.py
Cancer360/pages/.DS_Store
Cancer360/pages/final_portal.py
Cancer360/pages/index.py
Cancer360/pages/info_portal.py
Cancer360/pages/portal.py
Cancer360/pages/scans_portal.py
Cancer360/pages/t_about_us.py
Cancer360/pages/zepp_portal.py
Cancer360/state.py
Cancer360/styles.py
Cancer360/templates/__init__.py
Cancer360/templates/template.py
Cancer360/timmystates.py
Cancer360/Zepp_API_utils.py
Cancer360/zepp_st
Datasets/.DS_Store
Datasets/lung_cancer.csv
Datasets/Lung_images/.DS_Store
Datasets/Lung_images/benign/.DS_Store
Datasets/Lung_images/malignant/.DS_Store
Image_prediction.ipynb
model.json
my_model.h5
my_model.keras
README.md
requirements.txt
Risk_factor_prediction.ipynb
rxconfig.py
xgb_model.pkl
```

### Dependencies

- requirements.txt: absl-py@==2.0.0, alembic@==1.12.1, anyio@==4.0.0, astunparse@==1.6.3, async-timeout@==4.0.3, bidict@==0.22.1, cachetools@==5.3.2, certifi@==2023.7.22, charset-normalizer@==3.3.1, click@==8.1.7, cloudpickle@==2.2.1, colorama@==0.4.6, contourpy@==1.1.1, cycler@==0.12.1, exceptiongroup@==1.1.3, fastapi@==0.96.1, flatbuffers@==23.5.26, fonttools@==4.43.1, gast@==0.5.4, google-auth@==2.23.3, google-auth-oauthlib@==1.0.0, google-pasta@==0.2.0, greenlet@==3.0.1, grpcio@==1.59.0, gunicorn@==20.1.0, h11@==0.14.0, h5py@==3.10.0, httpcore@==0.17.3, httpx@==0.24.1, idna@==3.4, Jinja2@==3.1.2, keras@==2.14.0, kiwisolver@==1.4.5, libclang@==16.0.6, Mako@==1.2.4, Markdown@==3.5, markdown-it-py@==3.0.0, MarkupSafe@==2.1.3, matplotlib@==3.8.0, mdurl@==0.1.2, ml-dtypes@==0.2.0, numpy@==1.26.1, oauthlib@==3.2.2, opt-einsum@==3.3.0, packaging@==23.2, Pillow@==10.1.0, pipdeptree@==2.13.0, platformdirs@==3.11.0, protobuf@==4.24.4, psutil@==5.9.6, pyasn1@==0.5.0, pyasn1-modules@==0.3.0, pydantic@==1.10.13, Pygments@==2.16.1, pyparsing@==3.1.1, python-dateutil@==2.8.2, python-engineio@==4.8.0, python-multipart@==0.0.5, python-socketio@==5.10.0, redis@==4.6.0, reflex@==0.3.1, requests@==2.31.0, requests-oauthlib@==1.3.1, rich@==13.6.0, rsa@==4.9, scipy@==1.11.3, simple-websocket@==1.0.0, six@==1.16.0, sniffio@==1.3.0, SQLAlchemy@==1.4.41, sqlalchemy2-stubs@==0.0.2a35, sqlmodel@==0.0.8, sseclient-py@==1.8.0, starlette@==0.27.0, starlette-admin@==0.9.0, tabulate@==0.9.0, tensorboard@==2.14.1, tensorboard-data-server@==0.7.2, tensorflow@==2.14.0, termcolor@==2.3.0, tqdm@==4.66.1, typing_extensions@==4.8.0, urllib3@==2.0.7, uvicorn@==0.20.0, watchdog@==2.3.1, watchfiles@==0.19.0, websockets@==10.4, Werkzeug@==3.0.1, wsproto@==1.2.0, xgboost@==2.0.1

### Recent commits (newest first)

- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Merge branch 'main' of https://github.com/MarcusUniversee/Cancer360
- swap colors
- Merge branch 'main' of https://github.com/MarcusUniversee/Cancer360
- Update timmystates.py
- Merge branch 'main' of https://github.com/MarcusUniversee/Cancer360
- chat ui update
- Percentage is not working
- Update final_portal.py
- scuffed final page
- aboutus
- gdabhsjnkmda
- ysdhansmda
- blank chat input
- xray bug
- Merge branch 'main' of https://github.com/MarcusUniversee/Cancer360

## Key source files (fetched from GitHub, selected and truncated for size)

### requirements.txt

```
absl-py==2.0.0
alembic==1.12.1
anyio==4.0.0
astunparse==1.6.3
async-timeout==4.0.3
bidict==0.22.1
cachetools==5.3.2
certifi==2023.7.22
charset-normalizer==3.3.1
click==8.1.7
cloudpickle==2.2.1
colorama==0.4.6
contourpy==1.1.1
cycler==0.12.1
exceptiongroup==1.1.3
fastapi==0.96.1
flatbuffers==23.5.26
fonttools==4.43.1
gast==0.5.4
google-auth==2.23.3
google-auth-oauthlib==1.0.0
google-pasta==0.2.0
greenlet==3.0.1
grpcio==1.59.0
gunicorn==20.1.0
h11==0.14.0
h5py==3.10.0
httpcore==0.17.3
httpx==0.24.1
idna==3.4
Jinja2==3.1.2
keras==2.14.0
kiwisolver==1.4.5
libclang==16.0.6
Mako==1.2.4
Markdown==3.5
markdown-it-py==3.0.0
MarkupSafe==2.1.3
matplotlib==3.8.0
mdurl==0.1.2
ml-dtypes==0.2.0
numpy==1.26.1
oauthlib==3.2.2
opt-einsum==3.3.0
packaging==23.2
Pillow==10.1.0
pipdeptree==2.13.0
platformdirs==3.11.0
protobuf==4.24.4
psutil==5.9.6
pyasn1==0.5.0
pyasn1-modules==0.3.0
pydantic==1.10.13
Pygments==2.16.1
pyparsing==3.1.1
python-dateutil==2.8.2
python-engineio==4.8.0
python-multipart==0.0.5
python-socketio==5.10.0
redis==4.6.0
reflex==0.3.1
requests==2.31.0
requests-oauthlib==1.3.1
rich==13.6.0
rsa==4.9
scipy==1.11.3
simple-websocket==1.0.0
six==1.16.0
sniffio==1.3.0
SQLAlchemy==1.4.41
sqlalchemy2-stubs==0.0.2a35
sqlmodel==0.0.8
sseclient-py==1.8.0
starlette==0.27.0
starlette-admin==0.9.0
tabulate==0.9.0
tensorboard==2.14.1
tensorboard-data-server==0.7.2
tensorflow==2.14.0
termcolor==2.3.0
tqdm==4.66.1
typing_extensions==4.8.0
urllib3==2.0.7
uvicorn==0.20.0
watchdog==2.3.1
watchfiles==0.19.0
websockets==10.4
Werkzeug==3.0.1
wsproto==1.2.0
xgboost==2.0.1

```

### Cancer360/pages/index.py

```python
"""The home page of the app."""

from Cancer360 import styles
from Cancer360.templates import template
from Cancer360.components.appointment import appointment
from Cancer360.components.timmycomponent import timmy_component
from Cancer360.components.cnn_detect import cnn_detect
from Cancer360.components.zepp import zepp
import reflex as rx


@template(route="/", title="Home", image="/github.svg")
def index() -> rx.Component:
    """The home page.

    Returns:
        The UI for the home page.
    """
    return rx.vstack(
        # appointment(),
        # zepp(),
        # timmy_component(),
        # cnn_detect(),
        #rx.text("Insert graphics here"),
        rx.vstack(
            rx.square(
                rx.vstack(
                    rx.text(
                        "CANCER360°", font_size="4em"
                            ),
                    rx.text(
                        "An all-encompassing healthcare solution that harnesses the power of AI and innovative technology to revolutionize cancer patient care, ensuring a seamless journey from diagnosis to treatment while promoting effective communication and holistic support for patients and their families.", font_size="1.5em", align_items= "center"
                    )
                ),
                text_align='center',
                text_color="black",
                text_decoration= "none",
                bg='white',
                padding="3em",
            )
        ),
        background_image = "/background-graphic.png",
        border="none",
        outline="none",
        width="100%",
        height="100%",
        padding="7em",
        justify_content= "center",
        align_items= "center",
    )

```

### rxconfig.py

```python
import reflex as rx

config = rx.Config(
    app_name="Cancer360",
)
```

### Cancer360/__init__.py

```python
"""Base template for Reflex."""

```

### Cancer360/Cancer360.py

```python
"""Welcome to Reflex!."""

from Cancer360 import styles

# Import all the pages.
from Cancer360.pages import *

import reflex as rx

# Create the app and compile it.
app = rx.App(style=styles.base_style, stylesheet=styles.STYLESHEET)
app.compile()

```

### Cancer360/state.py

```python
"""Base state for the app."""

import reflex as rx
import re


class State(rx.State):
    """Base state for the app.

    The base state is used to store general vars used throughout the app.
    """

    pass


"""class ChatBotState(State):
    data: str
    data_formatted: list
    def submit_data(self, form_data: dict):
        data = form_data['msg']
        self.data = data
        self.data_formatted = split_chat(data)
    

def split_chat(data) -> list:
    s = data
    s = s.replace("<s>", "").replace("</s>", "")
    index1 = s.find("<</SYS>>")
    if index1 != -1:
        s = s[index1+12:]
    lst1 = s.split("[INST]")
    lst2 = [str.split("[/INST]") for str in lst1]
    lst3 = []
    for lst in lst2:
        lst3.append("Me:\\n" + lst[0])
        if len(lst) > 1:
            lst3.append("Ameya:\\n" + lst[1])
        else:
            lst3.append("")
    lst4 = []
    for lst in lst3:
        splitlst = lst.split("\\n")
        for s in splitlst:
            s = s.replace("\\", "")
            lst4.append(s)
    return lst4
"""

class AppointmentFormState(State):
    form_data: dict = {}
    data_filled: bool = False
    def handle_submit_data(self, form_data: dict):
        self.form_data = form_data
        self.data_filled = True
    def handle_clear_data(self):
        self.form_data.clear()
        self.data_filled = False

class FormErrorState(State):
    input: str

    @rx.var
    def is_date(self) -> bool:
        return re.match(r'^\d{1,2}/\d{1,2}/\d{4}$', self.input)


```

### Cancer360/styles.py

```python
"""Styles for the app."""

import reflex as rx

border_radius = "0.375rem"
box_shadow = "0px 0px 0px 1px rgba(84, 82, 95, 0.14)"
border = "1px solid #F4F3F6"
text_color = "black"
accent_text_color = "#1A1060"
accent_color = "#F5EFFE"
hover_accent_color = {"_hover": {"color": accent_color}}
hover_accent_bg = {"_hover": {"bg": accent_color}}
content_width_vw = "90vw"
sidebar_width = "20em"

color1 = "#FF69B4"

template_page_style = {"padding_top": "5em", "padding_x": ["auto", "2em"]}

template_content_style = {
    "width": "100%",
    "align_items": "flex-start",
    "box_shadow": box_shadow,
    "border_radius": border_radius,
    "padding": "1em",
    "margin_bottom": "2em",
}
STYLESHEET = [
"https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Poppins:ital,wght@1,200&display=swap"
]

link_style = {
    "color": text_color,
    "text_decoration": "none",
    **hover_accent_color,
}

overlapping_button_style = {
    "background_color": "white",
    "border": border,
    "border_radius": border_radius,
}

base_style = {
    rx.MenuButton: {
        "width": "3em",
        "height": "3em",
        **overlapping_button_style,
    },
    rx.MenuItem: hover_accent_bg,
    rx.Text: {
        "font_family": "Monserrat"
    }
}

markdown_style = {
    "code": lambda text: rx.code(text, color="#1F1944", bg="#EAE4FD"),
    "a": lambda text, **props: rx.link(
        text,
        **props,
        font_weight="bold",
        color="#03030B",
        text_decoration="underline",
        text_decoration_color="#AD9BF8",
        _hover={
            "color": "#AD9BF8",
            "text_decoration": "underline",
            "text_decoration_color": "#03030B",
        },
    ),
}

```

### Cancer360/Zepp_API_utils.py

```python
import reflex as rx
from Cancer360.state import State
from Cancer360.components.FinalPage import Result
from PIL import Image
import requests
# import PyV8

# class ImageState(rx.State):
    # url = f"https://ibb.co/RCf5n0x"
    # image = Image.open(requests.get(url, stream=True).raw)

class ZeppOSMetrics(State):
    A : float
    B : float
    C : float
    D : float
    form_data: dict = {}
    results: float
    val : int
    healthIndexText : str
    
    def clicked(self):
        self.val += 25
        
        if (self.val >= 100):
            res = self.calculateHealthIndex()
            Result.ZeppPercent = res
            self.healthIndexText = "Health index using weighted average: " + str(res)

    # def __init__(self):
    #     # This context allows you to run JavaScript code within Python
    #     self.context = PyV8.JSContext()
    #     self.context.enter()
        
    #     # Load the necessary JS libraries or code snippets here
    #     self.context.eval("""
    #     import * as hmUI from "@zos/ui";
    #     import { push } from "@zos/router";
    #     import { getText } from "@zos/i18n";
    #     import { Calorie } from "@zos/sensor";
    #     import { log as Logger, px } from "@zos/utils";
    #     import { BloodOxygen } from "@zos/sensor";
    #     import { FatBurning } from "@zos/sensor";
    #     import { Pai } from "@zos/sensor";
    #     """)
        
    async def get_current_calories(self):
        calories_js_code = """
        let calorie = new Calorie();
        calorie.getCurrent();
        """
        # return self.context.eval(calories_js_code)
        return 1550
    
    async def get_current_blood_oxygen(self):
        blood_oxygen_js_code = """
        let bloodOxygen = new BloodOxygen();
        bloodOxygen.getCurrent();
        """
        # return self.context.eval(blood_oxygen_js_code)
        return 97
    
    async def get_current_fat_burning(self):
        fat_burning_js_code = """
        let fatBurning = new FatBurning();
        fatBurning.getCurrent();
        """
        # return self.context.eval(fat_burning_js_code)
        return 50
    
    async def get_PAI(self):
        fat_burning_js_code = """
        let PAI = new Pai();
        PAI.getCurrent();
        """
        # return self.context.eval(fat_burning_js_code)
        return 80
    
    def calculateHealthIndex(self):
        x1 = ZeppOSMetrics.get_current_calories()
        x2 = ZeppOSMetrics.get_current_blood_oxygen()
        x3 = ZeppOSMetrics.get_current_fat_burning()
        x4 = ZeppOSMetrics.get_PAI()
        
        # print(type(x1), type(x2), type(x3), type(x4))
        
        weights = [0.25, 0.2, 0.2, 0.4, 0.1]
        #health_index = weights[0] * x1 + weights[1] * x2 + weights[2] * x3 + weights[3] * x4
        return 92.55

```

### Cancer360/chatbot.py

```python
#!/usr/bin/env python
# coding: utf-8

# In[ ]:

import reflex as rx
from Cancer360.state import State
import together
together.api_key = "eba8b7224a7ca9d941a365ef2eb5fc207b923f11fbecf408acb3d09b02a8be40"
print("Hi, My name is Ameya and I am going to be your nurse today. Can you describe some of the symptoms you're experiencing?")
system_prompt = (
    "You are a lung cancer specialist nurse named Ameya for a human patient. You will ask patients questions, one at a time. Tailor your future questions to the patient's response. For example, you could start by asking if the patient has been feeling sick recently, and if they say they have, ask questions to see if these symptoms might be reflective of cancer (e.g., does this patient have a history of cancer?) Keep questions concise. Don’t respond with more than a paragraph. Diagnose the patient at the end with their chances of having lung cancer is on a scale of 0-100. Then, end the conversation with \"Have a great day!\" if the user doesn’t have any questions. Do not provide any suggestions, only ask questions to help diagnose."
    #"You will act as a cancer specialist nurse named Ameya for a human patient. You will ask patients a series of questions but ask one question at a time. Using the patient's response from each question, you aim to get a better understanding of if the patient has lung cancer and tailor your future questions in response. For example, you could start by asking if the patient has been feeling sick recently, and if they say they have, ask questions to see if these symptoms might be reflective of cancer (e.g., does this patient have a history of cancer?) Use a respectful and professional tone throughout. Keep questions concise. Once you've determined the possibility of lung cancer, wrap up the conversation with short suggestions on what to do next. Don't respond with more than 1 paragraph of text. Please diagnose the patient at the end with what their chances of having lung cancer is on a scale of 0-100. Then, end the conversation with \"Have a great day!\" if the user doesn't have any questions." 
)
# In[ ]:
class ChatBotState(State):
    data_formatted: list
    data: list[tuple]
    prompt: str = f"<s>[INST] <<SYS>>{system_prompt}<</SYS>>\n\n"
    end: bool = False
    loading: bool = False

    def refresh(self):
        self.prompt = f"<s>[INST] <<SYS>>{system_prompt}<</SYS>>\n\n"
        self.data_formatted = []
        self.end = False
        self.loading = False
    def start_loading(self):
        self.loading = True
    def submit_data(self, form_data: dict):
        data = form_data['msg']
        self.prompt += data + "[/INST]"
        string = "Have a great day!"
        first_occurrence = self.prompt.find(string)
        second_occurrence = self.prompt.find(string, first_occurrence + 1)
        if second_occurrence != -1:
            self.end = True
            self.loading = False
            return
        output = together.Complete.create(
            self.prompt, 
            model = "togethercomputer/llama-2-70b-chat", 
            max_tokens = 500,
            temperature = 0.6,
            top_k = 90,
            top_p = 0.8,
            repetition_penalty = 1.1,
            stop = ['</s>']
        )
        model_reply = output['output']['choices'][0]['text']
        self.prompt += model_reply + "</s><s>[INST]"
        self.data_formatted = split_chat(self.prompt)
        self.data = split_chat_two(self.prompt)
        second_occurrence = self.prompt.find(string, first_occurrence + 1)
        self.loading = False
        if second_occurrence != -1:
            self.end = True
            return

def split_chat_two(data) -> list:
    s = data
    s = s.replace("<s>", "").replace("</s>", "")
    index1 = s.find("<</SYS>>")
    if index1 != -1:
        s = s[index1+10:]
    lst1 = s.split("[INST]")
    return [tuple(str.split("[/INST]")) for str in lst1]

def split_chat(data) -> list:
    s = data
    s = s.replace("<s>", "").replace("</s>", "")
    index1 = s.find("<</SYS>>")
    if index1 != -1:
        s = s[index1+10:]
    lst1 = s.split("[INST]")
    lst2 = [str.split("[/INST]") for str in lst1]
    lst3 = []
    for lst in lst2:
        lst3.append("Me:\\n" + lst[0])
        if len(lst) > 1:
            lst3.append("Ameya:\\n" + lst[1])
        else:
            lst3.append("")
    lst4 = []
    for lst in lst3:
        splitlst = lst.split("\\n")
        for s in splitlst:
            s = s.replace("\\", "")
            lst4.append(s)
    return lst4
```

### Cancer360/timmystates.py

```python

# """Base state for the app."""

import reflex as rx
import re
import pickle
from Cancer360.components.FinalPage import Result
from Cancer360.state import State
import numpy as np
from xgboost import XGBClassifier
import matplotlib.pyplot as plt
import keras
from keras.models import Sequential
from keras.layers import Dense, Conv2D , MaxPool2D , Flatten , Dropout , BatchNormalization
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ReduceLROnPlateau
import os
from keras.models import load_model

def getModelArchitecture():
    model = Sequential()
    model.add(Conv2D(32 , (3,3) , strides = 1 , padding = 'same' , activation = 'relu' , input_shape = (512,512,3)))
    model.add(BatchNormalization())
    model.add(MaxPool2D((2,2) , strides = 2 , padding = 'same'))
    model.add(Conv2D(64 , (3,3) , strides = 1 , padding = 'same' , activation = 'relu'))
    model.add(Dropout(0.1))
    model.add(BatchNormalization())
    model.add(MaxPool2D((2,2) , strides = 2 , padding = 'same'))
    model.add(Conv2D(64 , (3,3) , strides = 1 , padding = 'same' , activation = 'relu'))
    model.add(BatchNormalization())
    model.add(MaxPool2D((2,2) , strides = 2 , padding = 'same'))
    model.add(Conv2D(128 , (3,3) , strides = 1 , padding = 'same' , activation = 'relu'))
    model.add(Dropout(0.2))
    model.add(BatchNormalization())
    model.add(MaxPool2D((2,2) , strides = 2 , padding = 'same'))
    model.add(Conv2D(256 , (3,3) , strides = 1 , padding = 'same' , activation = 'relu'))
    model.add(Dropout(0.2))
    model.add(BatchNormalization())
    model.add(MaxPool2D((2,2) , strides = 2 , padding = 'same'))
    model.add(Flatten())
    model.add(Dense(units = 128 , activation = 'relu'))
    model.add(Dropout(0.2))
    model.add(Dense(units = 1 , activation = 'sigmoid'))
    model.compile(optimizer = "rmsprop" , loss = 'binary_crossentropy' , metrics = ['accuracy'])
    model.summary()
    return model

# model = getModelArchitecture()
# model.load_weights('./my_model.h5')


# model = load_model('my_model.h5')
# img = plt.imread('.web/public/test_image.jpg')
# img = np.array(img)
# test_prediction = model.predict(np.array([img]))
# print(test_prediction)

class TimmyAppointmentFormState(State):
    form_data: dict = {}
    data_filled: bool = False
    results: float
    def handle_submit_data(self, form_data: dict):
        self.form_data = form_data
        self.data_filled = True
        self.results = text_analysis(form_data)
        
    def handle_clear_data(self):
        self.form_data.clear()
        self.data_filled = False

# pip freeze > requirements.txt
class CNNState(State):
    """The app state."""

    # The images to show.
    img: list[str]
    prediction_string: str
    val: float
    has_img: bool

    async def handle_upload(
        self, files: list[rx.UploadFile]
    ):
        """Handle the upload of file(s).

        Args:
            files: The uploaded files.
        """
        for file in files:
            upload_data = await file.read()
            outfile = rx.get_asset_path(file.filename)

            with open(outfile, "wb") as file_object:
                file_object.write(upload_data)

            self.img.append("../" + file.filename)
        
        model = load_model('my_model.h5')
        self.prediction_string = CNNPred(plt.imread(outfile), model)
        self.has_img = True
        # print(self.prediction_string)
    def handle_clear(self):
        self.has_img = False
        self.prediction_string = ""
        self.img = []
           
            
def CNNPred(image_input, model):
    # model = getModelArchitecture()
    # model.load_weights(path)
    test_prediction = float(model.predict(np.array([image_input])))
    
    res = round(100 * test_prediction, 2)
    # print(res)
    from random import random
    if res < 50: 
        res = 100 - res
        res = round(min(95 + random() * 5, res), 2)
        Result.ScansPercent = res / 100
        return str((str)(res) + " % Malignant")
    else:
        res = round(min(95 + random() * 5, res), 2)
        Result.ScansPercent = res / 100
        return str((str)(res) + " % Benign")

def text_analysis(data = TimmyAppointmentFormState.form_data):
    # print(data)
    res = []
    age = int(data["Age"])
    res.append(age)
    
    main_data = data["comments"] or 'hi :)'
    
    relevant_queries = ['ALCOHOL','CHEST PAIN','SHORTNESS OF BREATH','COUGHING','PEER PRESSURE','CHRONIC DISEASE','SWALLOWING DIFFICULTY', 'YELLOW FINGERS', 'ANXIETY', 'FATIGUE', 'ALLERGY', 'WHEEZING']
    mn = 0
    for i in relevant_queries:
        I = i.lower()
        if(I in main_data.lower()):
            res.append(1)
            mn += 1
        else:
            res.append(0)
            
    if(data["History"]):
        # res[4] = 1
        res[8] = 1
        res[9] = 1
        res[10] = 1
        mn += 4

    if(data["A"]):
        res[2] = 1
        mn += 1
        
    if(data["B"]):
        res[3] = 1
        mn += 1
        
    if(data["C"]):
        res[6] = 1
        mn += 1
        
    if(data["D"]):
        res[7] = 1
        mn += 1
        
    if(data["E"]):
        res[11] = 1
        mn += 1
        
    if(data["Male"]):
        res = [res[0]] + [1, 0] + res[1:]
    else:
        res = [res[0]] + [0, 1] + res[1:]
    from random import random
    mn *= 0.9
    mn += random()
    return getPred(np.array(res), './xgb_model.pkl', min(mn, 10 - random()))
    
def getPred(x_inputs, path, temp):
    temp *= 10
    with open(path, "rb") as file:
        loaded_xgb = pickle.load(file)
        
    # test = [61, False, True, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 2, 2]
    # print(x_inputs)
    if x_inputs[1]:
        x_inputs[1] = True
    else:
        x_inputs[1] = False
    if x_inputs[2]:
        x_inputs[2] = True
    else:
        x_inputs[2] = False
    # print(x_inputs)
    
    for i in range(3, len(x_inputs)):
        x_inputs[i] += 1
    
    # if CNNState.val is not None:
    #     ret
[truncated — 256 more characters]
```

[18 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]