diff --git a/README.md b/README.md index 265940a..474bf54 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@

- AFusion is a user-friendly graphical interface designed to simplify the process of AlphaFold 3 installation and predictions, making it accessible to users who prefer a GUI over command-line interactions. + AFusion is a user-friendly graphical interface designed to simplify the process of AlphaFold 3 installation, prediction and visualization, making it accessible to users who prefer a GUI over command-line interactions.

**[Demo site](https://af3gui.streamlit.app/) (generate input JSON files ONLY)** @@ -205,8 +205,8 @@ If you encounter any issues during installation or usage, please refer to the re - [X] ~~📄 **Bulid Documentation:** Tutorial for using the AFusion API in Python scripts for batch predictions.~~ - [X] ~~♻️ **Refactor Code and Publish to PyPI**: Refactor the project code for improved modularity and maintainability, and publish the latest version to PyPI for easy installation.~~ -- [ ] ~~🔗 **Develop AlphaFold result analysis system**: Design and implement a comprehensive analysis pipeline for AlphaFold prediction results.~~ - - [ ] Update the system. +- [X] ~~🔗 **Develop AlphaFold result analysis system**: Design and implement a comprehensive analysis pipeline for AlphaFold prediction results.~~ + - [X] ~~Update the system.~~ - [ ] ⚛️ **Preset Common Small Molecules & Metal Ions**: Add a dedicated section for quick access to commonly used small molecules and metal ions. - [ ] 🛠️ **New Tool for Chemical Small Molecules**: Develop a new tool to handle and model chemical small molecules, supporting seamless integration into the prediction pipeline. - [X] ~~🖥️ **Add Console Output**: Implement a backend console for output to track processes and debug more effectively.~~ diff --git a/afusion.egg-info/PKG-INFO b/afusion.egg-info/PKG-INFO index 4064ef8..544d175 100644 --- a/afusion.egg-info/PKG-INFO +++ b/afusion.egg-info/PKG-INFO @@ -1,7 +1,7 @@ Metadata-Version: 2.1 Name: afusion -Version: 1.2.0 -Summary: A Streamlit app for running AlphaFold 3 predictions +Version: 1.2.2 +Summary: AFusion: AlphaFold 3 GUI & Toolkit with Visualization Home-page: https://github.com/Hanziwww/AlphaFold3-GUI Author: Han Wang Author-email: marspenman@gmail.com @@ -47,11 +47,13 @@ Requires-Dist: plotly

- AFusion is a user-friendly graphical interface designed to simplify the process of AlphaFold 3 installation and predictions, making it accessible to users who prefer a GUI over command-line interactions. + AFusion is a user-friendly graphical interface designed to simplify the process of AlphaFold 3 installation, prediction and visualization, making it accessible to users who prefer a GUI over command-line interactions.

**[Demo site](https://af3gui.streamlit.app/) (generate input JSON files ONLY)** +[**Usable visualization site**](https://af3vis.streamlit.app/) **(fully usable)** + ## Table of Contents - [Features](#features) @@ -224,7 +226,8 @@ If you encounter any issues during installation or usage, please refer to the re - [X] ~~📄 **Bulid Documentation:** Tutorial for using the AFusion API in Python scripts for batch predictions.~~ - [X] ~~♻️ **Refactor Code and Publish to PyPI**: Refactor the project code for improved modularity and maintainability, and publish the latest version to PyPI for easy installation.~~ -- [ ] 🔗 **Develop AlphaFold result analysis system**: Design and implement a comprehensive analysis pipeline for AlphaFold prediction results. +- [X] ~~🔗 **Develop AlphaFold result analysis system**: Design and implement a comprehensive analysis pipeline for AlphaFold prediction results.~~ + - [X] ~~Update the system.~~ - [ ] ⚛️ **Preset Common Small Molecules & Metal Ions**: Add a dedicated section for quick access to commonly used small molecules and metal ions. - [ ] 🛠️ **New Tool for Chemical Small Molecules**: Develop a new tool to handle and model chemical small molecules, supporting seamless integration into the prediction pipeline. - [X] ~~🖥️ **Add Console Output**: Implement a backend console for output to track processes and debug more effectively.~~ diff --git a/afusion/app.py b/afusion/app.py index 1596998..bb6e667 100644 --- a/afusion/app.py +++ b/afusion/app.py @@ -22,7 +22,7 @@ collect_ligand_sequence_data ) from afusion.bonds import handle_bond -from afusion.utils import compress_output_folder +from afusion.utils import log_to_ga, compress_output_folder # Import visualization functions from afusion.visualization import ( @@ -90,6 +90,10 @@ def get_color_from_bfactor(bfactor): return 'grey' # Default color def main(): + + # Log to Google Analytics when the app starts + log_to_ga() + # Set page configuration and theme st.set_page_config( page_title="AFusion: AlphaFold 3 GUI", @@ -415,8 +419,11 @@ def find_file_by_suffix(directory_path, suffix): # Load the data structure, cif_content = read_cif_file(required_files["model.cif"]) residue_bfactors, ligands = extract_residue_bfactors(structure) - pae_matrix = extract_pae_from_json(required_files["confidences.json"]) + pae_matrix, token_chain_ids = extract_pae_from_json(required_files["confidences.json"]) summary_data = extract_summary_confidences(required_files["summary_confidences.json"]) + chain_ids = list(set(token_chain_ids)) + chain_ids.sort() # Sort for consistency + logger.debug("Successfully loaded data from output folder.") # Display the visualizations @@ -436,10 +443,10 @@ def find_file_by_suffix(directory_path, suffix): with col2: # Visualize the PAE matrix - visualize_pae(pae_matrix) + visualize_pae(pae_matrix, token_chain_ids) # Display summary data - display_summary_data(summary_data) + display_summary_data(summary_data, chain_ids) else: st.error("AlphaFold 3 execution did not complete successfully. Please check the logs.") logger.error("AlphaFold 3 execution did not complete successfully.") diff --git a/afusion/utils.py b/afusion/utils.py index 8f4bdbc..f0c42ea 100644 --- a/afusion/utils.py +++ b/afusion/utils.py @@ -1,9 +1,58 @@ +# utils.py + import os -import zipfile -import io +import uuid +import json +import requests from loguru import logger +import streamlit as st + +def log_to_ga(): + # Replace with your Measurement ID + measurement_id = "G-42P6TDX7LH" + # Get API secret from environment variable + api_secret = "Z-CSzz9hSsK3MSaxJjB8sQ" + + if not api_secret: + logger.error("API secret for Google Analytics not found. Please set the GA_API_SECRET environment variable.") + return + + url = f"https://www.google-analytics.com/mp/collect?measurement_id={measurement_id}&api_secret={api_secret}" + + # Generate or retrieve a unique client ID for each user session + if 'client_id' not in st.session_state: + st.session_state['client_id'] = str(uuid.uuid4()) + + client_id = st.session_state['client_id'] + logger.debug(f"Client ID: {client_id}") + + payload = { + "client_id": client_id, + "events": [{ + "name": "app_start", + "params": {} + }] + } + + headers = { + 'Content-Type': 'application/json' + } + + try: + response = requests.post(url, json=payload, headers=headers) + if response.status_code != 204: + logger.error(f"Failed to log to Google Analytics: {response.content}") + else: + logger.info("Successfully logged to Google Analytics") + except Exception as e: + logger.error(f"Exception occurred while logging to Google Analytics: {e}") def compress_output_folder(output_folder_path, job_output_folder_name): + import os + import zipfile + import io + from loguru import logger + # Create a ZIP file in memory zip_buffer = io.BytesIO() with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zipf: diff --git a/afusion/visualization.py b/afusion/visualization.py index 36307de..f3d733e 100644 --- a/afusion/visualization.py +++ b/afusion/visualization.py @@ -28,8 +28,9 @@ def read_cif_file(file_path): def extract_pae_from_json(file_path): with open(file_path, 'r') as file: data = json.load(file) - pae = np.array(data.get("pae", [])) - return pae + pae = np.array(data.get("pae", []), dtype=np.float16) # Use np.float16 + token_chain_ids = data.get("token_chain_ids", []) + return pae, token_chain_ids def extract_summary_confidences(file_path): with open(file_path, 'r') as file: @@ -49,8 +50,9 @@ def read_cif_file_obj(file_obj): def extract_pae_from_json_obj(file_obj): data = json.load(file_obj) - pae = np.array(data.get("pae", [])) - return pae + pae = np.array(data.get("pae", []), dtype=np.float16) # Use np.float16 + token_chain_ids = data.get("token_chain_ids", []) + return pae, token_chain_ids def extract_summary_confidences_obj(file_obj): data = json.load(file_obj) @@ -134,7 +136,7 @@ def visualize_structure(residue_bfactors, ligands, cif_content, background_color selection = { 'chain': ligand['chain_id'], 'resi': ligand['resseq'], - 'atom': ligand['atom_name'] + 'atom': ligand['atom_name'] # Corrected line } style = {'stick': {'color': color}} view.addStyle(selection, style) @@ -170,7 +172,7 @@ def display_visualization_header(): """ st.markdown(color_mapping_html, unsafe_allow_html=True) -def visualize_pae(pae_matrix): +def visualize_pae(pae_matrix, token_chain_ids): st.write("### Predicted Aligned Error (PAE)") fig = px.imshow( pae_matrix, @@ -180,37 +182,81 @@ def visualize_pae(pae_matrix): y="Residue index", color="PAE (Å)" ), + zmin=0.0, + zmax=31.75 ) - fig.update_layout( - margin=dict(l=20, r=20, t=30, b=80), - coloraxis_colorbar=dict( - orientation='h', - yanchor='bottom', - y=-0.5, - xanchor='center', - x=0.5, - title_side='bottom' - ), - xaxis=dict( - tickfont=dict(size=12), - ) - ) + # Draw chain boundaries + if token_chain_ids: + chain_boundaries = [] + prev_chain = token_chain_ids[0] + for idx, chain_id in enumerate(token_chain_ids): + if chain_id != prev_chain: + chain_boundaries.append(idx - 0.5) + prev_chain = chain_id + for boundary in chain_boundaries: + fig.add_shape( + type="line", + x0=boundary, + y0=0, + x1=boundary, + y1=len(token_chain_ids), + line=dict(color="red", width=1) + ) + fig.add_shape( + type="line", + x0=0, + y0=boundary, + x1=len(token_chain_ids), + y1=boundary, + line=dict(color="red", width=1) + ) st.plotly_chart(fig, use_container_width=True) -def display_summary_data(summary_data): +def display_summary_data(summary_data, chain_ids): st.write("### Summary of Confidence Metrics") - # Convert summary data to DataFrame for better display - df = pd.DataFrame(list(summary_data.items()), columns=['Metric', 'Value']) - # Format arrays for better readability - for index, row in df.iterrows(): - if isinstance(row['Value'], list): - df.at[index, 'Value'] = json.dumps(row['Value'], indent=2) - - st.table(df) + # Map chain-level metrics to chain IDs + chain_metrics = {} + for key in ['chain_iptm', 'chain_ptm']: + if key in summary_data: + values = summary_data[key] + if len(values) == len(chain_ids): + chain_metrics[key] = dict(zip(chain_ids, values)) + else: + st.warning(f"The number of values in {key} does not match the number of chains.") + + # Display chain-level metrics + for key, metrics in chain_metrics.items(): + st.write(f"#### {key}") + df = pd.DataFrame.from_dict(metrics, orient='index', columns=[key]) + st.table(df.style.set_table_styles( + [{'selector': 'th, td', 'props': [('border', '1px solid black')]}] + )) + + # Display pair metrics as matrices + for key in ['chain_pair_iptm', 'chain_pair_pae_min']: + pair_metrics = summary_data.get(key, {}) + if pair_metrics: + st.write(f"#### {key}") + if len(pair_metrics) == len(chain_ids): + df = pd.DataFrame(pair_metrics, index=chain_ids, columns=chain_ids) + st.table(df.style.set_table_styles( + [{'selector': 'th, td', 'props': [('border', '1px solid black')]}] + )) + else: + st.warning(f"The dimensions of {key} do not match the number of chains.") + + # Display other metrics + other_metrics = {k: v for k, v in summary_data.items() if k not in ['chain_iptm', 'chain_ptm', 'chain_pair_iptm', 'chain_pair_pae_min']} + if other_metrics: + st.write("#### Other Metrics") + df = pd.DataFrame(list(other_metrics.items()), columns=['Metric', 'Value']) + st.table(df.style.set_table_styles( + [{'selector': 'th, td', 'props': [('border', '1px solid black')]}] + )) # ======================================== -# Main application +# Main Application # ======================================== def main(): @@ -288,10 +334,14 @@ def main(): # Read and process files structure, cif_content = read_cif_file_obj(model_cif_file) residue_bfactors, ligands = extract_residue_bfactors(structure) - pae_matrix = extract_pae_from_json_obj(confidences_json_file) + pae_matrix, token_chain_ids = extract_pae_from_json_obj(confidences_json_file) summary_data = extract_summary_confidences_obj(summary_confidences_file) logger.info("Successfully loaded and processed uploaded files.") + # Get chain ID list + chain_ids = list(set(token_chain_ids)) + chain_ids.sort() # Sort for consistency + # Display visualization results st.markdown('
', unsafe_allow_html=True) st.header("🌟 Visualizations") @@ -311,11 +361,11 @@ def main(): with col2: # Visualize PAE matrix - visualize_pae(pae_matrix) + visualize_pae(pae_matrix, token_chain_ids) # Display summary data st.markdown('
', unsafe_allow_html=True) - display_summary_data(summary_data) + display_summary_data(summary_data, chain_ids) except Exception as e: st.error(f"An error occurred while processing the files: {e}") diff --git a/docs/source/conf.py b/docs/source/conf.py index 78c45d4..168bf0e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -7,7 +7,7 @@ project = 'AFusion' copyright = '2024, Hanzi' author = 'Hanzi' -release = '1.2.0' +release = '1.2.1' # -- General configuration --------------------------------------------------- extensions = [ diff --git a/docs/source/index.md b/docs/source/index.md index 6a8edd8..a6d30c8 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -1,15 +1,12 @@ # 🔬 AFusion: AlphaFold 3 GUI & Toolkit ## Introduction -**AFusion** is a user-friendly graphical interface designed to simplify AlphaFold 3 predictions, making advanced protein structure modeling accessible to everyone. Whether you prefer a GUI over command-line interactions or need an API for batch predictions, AFusion has you covered. +**AFusion** is a user-friendly graphical interface designed to simplify AlphaFold 3 usage, making advanced protein structure modeling accessible to everyone. Whether you prefer a GUI over command-line interactions or need an API for batch predictions, AFusion has you covered. [**Demo Site**](https://af3gui.streamlit.app/) *(generates input JSON files ONLY)* ## Features -### **🌟 New Feature!** -- **AlphaFold 3 Output Analysis System**: Automatically analyze and visualize results with customizable visualizations and generate detailed PDF reports for streamlined insights. - - **🧭 Guided Installation**: GUI-based installer to simplify the installation process, easily set up the application through step-by-step guidance. - **✨ Intuitive Interface**: Easily configure job settings, sequences, and execution parameters through a clean and modern GUI. - **📋 Entity Management**: Add multiple entities (Protein, RNA, DNA, Ligand) with support for modifications, MSA options, and templates. @@ -19,6 +16,9 @@ - **🖥️ Console Output**: Track processes and debug more effectively with backend console output. - **🧩 API for Batch Predictions**: Perform batch predictions using the AFusion API in Python scripts. +### **🌟 New Feature!** +- **AlphaFold 3 Output Analysis System**: Automatically analyze and visualize results with customizable visualizations and generate detailed PDF reports for streamlined insights. + ## Acknowledgements - **AlphaFold 3**: This GUI is designed to work with [AlphaFold 3](https://github.com/google-deepmind/alphafold3) by DeepMind. diff --git a/docs/source/release.md b/docs/source/release.md index 0d683dc..e3b720b 100644 --- a/docs/source/release.md +++ b/docs/source/release.md @@ -1,6 +1,15 @@ # Release Notes -## v1.2.0 "Visualization & Analysis" (Release Date: December 21, 2024) +## v1.2.1 "Visualization Optimized" (Release Date: November 23, 2024) + +### Improvements + +- **Visualization Performance Optimization**: Enhanced the visualization module to improve rendering speed and reduce memory usage, enabling smoother analysis of large AlphaFold 3 output files. + +- **Stability Improvements**: Addressed minor bugs and improved the stability of the visualization tools, ensuring a seamless user experience during structure analysis. + + +## v1.2.0 "Visualization & Analysis" (Release Date: November 21, 2024) ### New Features diff --git a/setup.py b/setup.py index 421e1b5..fb765b6 100644 --- a/setup.py +++ b/setup.py @@ -2,10 +2,10 @@ setup( name='afusion', - version='1.2.0', + version='1.2.2', author='Han Wang', author_email='marspenman@gmail.com', - description='A Streamlit app for running AlphaFold 3 predictions', + description='AFusion: AlphaFold 3 GUI & Toolkit with Visualization', long_description=open('README.md', encoding='utf-8').read(), long_description_content_type='text/markdown', url='https://github.com/Hanziwww/AlphaFold3-GUI',