import csv
import os
from pathlib import Path
import networkx as nx
from tommy.controller.graph_controller import GraphController
from tommy.controller.topic_modelling_controller import \
TopicModellingController
from tommy.support.types import Document_topics
from tommy.datatypes.exports import NxExport, MatplotLibExport
def hex_to_rgb(hex_color: str) -> tuple:
"""
Convert hex color string to RGB tuple
:param hex_color: Hex color string (e.g., "#RRGGBB")
:return: RGB tuple (e.g., (R, G, B))
"""
hex_color = hex_color.lstrip('#')
return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4))
[docs]
class ExportController:
"""Class for exporting graphs and networks to file"""
_graph_controller: GraphController = None
_topic_modelling_controller: TopicModellingController = None
document_topics: Document_topics = []
[docs]
def is_topic_modelling_done(self) -> bool:
"""Check if topic modeling has been run"""
try:
return self._graph_controller.get_number_of_topics() > 0
except RuntimeError:
return False
[docs]
def export_networks(self, path: str) -> list[str]:
"""
Exports networks to gexf file for all available nx exports
:param path: path to the folder where to save the gexf files
:return: None
"""
errors = []
try:
nx_exports = self._graph_controller.get_all_nx_exports()
for nx_export in nx_exports:
new_path = os.path.join(path, f"{nx_export.vis_name}.gexf")
# Create a new graph with the same nodes and edges to
# store colors
graph_with_colors = nx.Graph(nx_export.graph)
# Store node and edge colors in the new graph
for node, data in graph_with_colors.nodes(data=True):
if 'color' in data:
color = data['color']
if isinstance(color, str):
color = hex_to_rgb(color)
graph_with_colors.nodes[node]['viz'] = \
{'color': {'r': color[0],
'g': color[1],
'b': color[2]}}
for u, v, data in graph_with_colors.edges(data=True):
if 'color' in data:
color = data['color']
if isinstance(color, str):
color = hex_to_rgb(color)
graph_with_colors[u][v]['viz'] = \
{'color': {
'r': color[0],
'g': color[1],
'b': color[2]}}
nx.write_gexf(graph_with_colors, new_path)
except Exception as e:
errors.append(f"Error exporting networks: {repr(e)}")
return errors
[docs]
def export_graphs(self, path: str) -> list[str]:
""""
Exports graphs to png file for all available visualizations
:param path: path to the folder where to save the png files
:return: None
"""
errors = []
try:
graph_exports = self._graph_controller.get_all_visualizations(
ignore_cache=True)
for graph_export in graph_exports:
topic_string = ("" if graph_export.topic_num is None
else f" - Topic {graph_export.topic_num + 1}")
new_path = os.path.join(path, f"{graph_export.vis_name}"
f"{topic_string}.png")
figure = graph_export.figure
figure.savefig(new_path)
except Exception as e:
errors.append(f"Error exporting graphs: {repr(e)}")
return errors
[docs]
def export_topic_words_csv(self, path: str) -> list[str]:
"""
Export words related to topics to a CSV file.
:param path: Path to the CSV file
:return: None
"""
errors = []
try:
with open(path, 'w', newline='') as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(
['Topic', 'Word', 'Score']) # Write header row
for i in range(self._graph_controller.get_number_of_topics()):
topic_name = f"Topic {i + 1}"
topic = self._graph_controller.get_topic_with_scores(i,
100)
for word, score in zip(topic.top_words, topic.word_scores):
csv_writer.writerow([topic_name, word, score])
except Exception as e:
errors.append(
f"Error exporting topic words to CSV: {repr(e)}")
return errors
[docs]
def on_document_topics_calculated(
self,
document_topics: Document_topics) -> None:
"""
Update stored topic document correspondence reference.
:param document_topics: The list of documents related to topics
:return: None
"""
self.document_topics = document_topics
[docs]
def export_document_topics_csv(self, path: str) -> list[str]:
"""
Export documents related to topics to a CSV file.
:param path: Path to the CSV file
:return: List of error messages
"""
errors = []
try:
with open(path, 'w', newline='') as csvfile:
csv_writer = csv.writer(csvfile)
header = ['Filename'] + ['Length'] + ['Author'] + ['Title'] + [
'Date'] + ['Path'] + [f'Topic {i + 1} Probability'
for i in range(
len(self.document_topics[0][1]))]
csv_writer.writerow(header)
for metadata, probabilities in self.document_topics:
row = [metadata.name + "." + metadata.format,
str(metadata.length), metadata.author,
metadata.title, str(metadata.date),
metadata.path] + probabilities
csv_writer.writerow(row)
except Exception as e:
errors.append(f"Error exporting document topics to CSV: {repr(e)}")
return errors
[docs]
def set_controller_refs(
self,
graph_controller: GraphController,
topic_modelling_controller: TopicModellingController) -> None:
self._graph_controller = graph_controller
self._topic_modelling_controller = topic_modelling_controller
topic_modelling_controller.calculate_topic_documents_event.subscribe(
self.on_document_topics_calculated)
"""
This program has been developed by students from the bachelor Computer Science
at Utrecht University within the Software Project course.
© Copyright Utrecht University
(Department of Information and Computing Sciences)
"""