Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ jobs:
run: |
chmod +x scripts/setup-env.sh
./scripts/setup-env.sh

- name: Verify installed Python packages
run: |
source .venv/bin/activate
pip list


- name: Verify R installation and WGCNA
shell: bash
Expand All @@ -52,6 +58,7 @@ jobs:

- name: Run tests with pytest
run: |
source .venv/bin/activate
pytest --cov=bioneuralnet --cov-report=xml tests/

- name: Upload coverage to Codecov
Expand Down
2 changes: 1 addition & 1 deletion bioneuralnet.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Provides-Extra: cuda117
Provides-Extra: dev
License-File: LICENSE

# BioNeuralNet: A Graph-Based Multi-Omics Integration and Embedding Framework for Advanced Analytics
# BioNeuralNet: A Graph-Based Multi-Omics Integration and Embedding Framework for Advanced analysis

![License](https://img.shields.io/badge/license-MIT-blue.svg)
![PyPI](https://img.shields.io/pypi/v/bioneuralnet)
Expand Down
2 changes: 1 addition & 1 deletion bioneuralnet/analysis/base_feature_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(
"""
self.num_features = num_features
self.selection_method = selection_method
self.output_dir = output_dir if output_dir else self._create_output_dir()
self.output_dir = output_dir #if output_dir else self._create_output_dir()
self.logger = get_logger(__name__)
self.logger.info("Initialized BaseFeatureSelector.")

Expand Down
61 changes: 20 additions & 41 deletions bioneuralnet/analysis/dynamic_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@
from typing import Optional
import pandas as pd
import networkx as nx
import pyvis
from pyvis.network import Network
from jinja2 import Environment, FileSystemLoader
from ..utils.logger import get_logger


class DynamicVisualizer:
"""
DynamicVisualizer Class for Generating Interactive Network Visualizations.

Utilizes Pyvis to create and save interactive HTML visualizations of networks.
"""

def __init__(
self,
adjacency_matrix: pd.DataFrame,
Expand All @@ -25,20 +20,6 @@ def __init__(
width: str = "100%",
height: str = "800px"
):
"""
Initializes the DynamicVisualizer instance.

Args:
adjacency_matrix (pd.DataFrame): Adjacency matrix representing the network.
layout (str, optional): Layout algorithm for network visualization ('spring', 'hierarchical', etc.). Defaults to 'spring'.
notebook (bool, optional): Whether to generate a notebook-compatible visualization. Defaults to False.
bgcolor (str, optional): Background color of the visualization. Defaults to '#ffffff'.
font_color (str, optional): Font color for node labels. Defaults to 'black'.
output_dir (str, optional): Directory to save the visualization HTML file. If None, saves in the current directory. Defaults to None.
output_filename (str, optional): Filename for the saved visualization HTML file. Defaults to "dynamic_network.html".
width (str, optional): Width of the visualization. Defaults to "100%".
height (str, optional): Height of the visualization. Defaults to "800px".
"""
self.adjacency_matrix = adjacency_matrix
self.layout = layout
self.notebook = notebook
Expand All @@ -52,47 +33,45 @@ def __init__(
self.logger.info("Initialized DynamicVisualizer.")

def generate_graph(self) -> nx.Graph:
"""
Converts the adjacency matrix into a NetworkX graph.

Returns:
nx.Graph: NetworkX graph constructed from the adjacency matrix.
"""
self.logger.info("Generating NetworkX graph from adjacency matrix.")
self.logger.info("Generating NetworkX graph from adjacency_matrix.")
G = nx.from_pandas_adjacency(self.adjacency_matrix)
self.logger.info(f"Graph generated with {G.number_of_nodes()} nodes and {G.number_of_edges()} edges.")
if G.number_of_nodes() == 0:
self.logger.error("Generated graph is empty.")
raise nx.NetworkXError("Generated graph is empty.")
return G

def visualize(self, G: nx.Graph):
"""
Generates and saves an interactive visualization of the network.

Args:
G (nx.Graph): NetworkX graph to visualize.
"""
self.logger.info(f"Generating interactive visualization with layout: {self.layout}")

net = Network(height=self.height, width=self.width, bgcolor=self.bgcolor, font_color=self.font_color, notebook=self.notebook)
# Load the default template from pyvis/templates
templates_dir = os.path.join(os.path.dirname(pyvis.__file__), 'templates')
env = Environment(loader=FileSystemLoader(templates_dir))
template = env.get_template('template.html')

net = Network(height=self.height, width=self.width, bgcolor=self.bgcolor, font_color=self.font_color, notebook=False)

# Assign the loaded template to net.template
net.template = template

if self.layout == 'hierarchical':
net.barnes_hut()
elif self.layout == 'spring':
net.force_atlas_2based()
else:
self.logger.warning(f"Layout '{self.layout}' not recognized. Using default layout.")
self.logger.warning(f"Layout '{self.layout}' not recognized. Falling back to spring layout.")

net.from_nx(G)

for node in net.nodes:
node['title'] = node['id']
node['label'] = node['id']
node['color'] = 'skyblue'

for edge in net.edges:
edge['color'] = 'gray'

os.makedirs(self.output_dir, exist_ok=True)
output_path = os.path.join(self.output_dir, self.output_filename)

net.show(output_path)
self.logger.info(f"Interactive network visualization saved to {output_path}")
8 changes: 8 additions & 0 deletions bioneuralnet/analysis/static_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,18 @@ def generate_graph(self) -> nx.Graph:

Returns:
nx.Graph: NetworkX graph constructed from the adjacency matrix.

Raises:
nx.NetworkXError: If the generated graph is empty.
"""
self.logger.info("Generating NetworkX graph from adjacency matrix.")
G = nx.from_pandas_adjacency(self.adjacency_matrix)
self.logger.info(f"Graph generated with {G.number_of_nodes()} nodes and {G.number_of_edges()} edges.")

if G.number_of_nodes() == 0:
self.logger.error("Generated graph is empty.")
raise nx.NetworkXError("Generated graph is empty.")

return G

def visualize(self, G: nx.Graph):
Expand Down
4 changes: 2 additions & 2 deletions bioneuralnet/clustering/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .hierarchical import HierarchicalClustering
from .pagerank import PageRankClustering
from .pagerank import PageRank

__all__ = ['HierarchicalClustering', 'PageRankClustering']
__all__ = ['HierarchicalClustering', 'PageRank']
2 changes: 1 addition & 1 deletion bioneuralnet/clustering/hierarchical.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(
self.n_clusters = n_clusters
self.linkage = linkage
self.affinity = affinity
self.output_dir = output_dir if output_dir else self._create_output_dir()
self.output_dir = output_dir #if output_dir else self._create_output_dir()

self.logger = get_logger(__name__)
self.logger.info("Initialized HierarchicalClustering with the following parameters:")
Expand Down
Loading
Loading