commit daa1115964839f7638b0f2d37cbbbb5d221e68e7 Author: rnsrk Date: Tue Nov 12 03:37:02 2024 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d743995 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +data diff --git a/app.py b/app.py new file mode 100644 index 0000000..ea0e5e1 --- /dev/null +++ b/app.py @@ -0,0 +1,120 @@ +from flask import Flask, render_template, redirect, url_for +import pandas as pd +from charts.charts import bar_chart, bar_chart_with_special_legend, point_chart, pie_chart + +app = Flask(__name__) + +# Read the CSV file + +def translate_csv(file, translation_dict): + with open(file, 'r') as f: + text = f.read() + for key, value in translation_dict.items(): + text = text.replace(key, value) + with open('data/umfrage2survey.csv', 'w') as f: + f.write(text) + +translation_dict = { + 'Wie sind Sie auf WissKI aufmerksam geworden?': 'How did you hear about WissKI?', + 'In welchem Bereich verwenden Sie WissKI?': 'In which area do you use WissKI?', + 'Wie lange arbeiten Sie mit WissKI?': 'How long do you work with WissKI?', + 'Bedeutung von Softwarefeatures und Eigenschaften': 'Importance of software features and properties', + 'In welcher Rolle benutzen Sie WissKI?': 'In which role do you use WissKI?', + 'Haben Sie Erfahrung mit anderen Forschungsdaten-Management-Systemen?': 'Do you have experience with other research data management systems?', + 'Haben Sie Zugriff auf kompetenten IT- und Systemadministrationssupport innerhalb Ihres Projektes bzw. Institution?': 'Do you have access to competent IT and system administration support within your project or institution?', + 'Arbeitet Ihre Institution/ Unternehmen das erste Mal mit WissKI?': 'Is this the first time your institution/company has worked with WissKI?', + 'Wie viele Stunden stehen Ihnen für die Arbeit mit WissKI wöchentlich zur Verfügung?': 'How many hours a week do you have available for working with WissKI?', + 'Welchen Community-Angeboten haben Sie mindestens einmal wahrgenommen?': 'Which community offers have you used at least once?', + 'Im Verhältnis zu anderen Forschungsdaten-Management-Systemen verorte ich die Qualität von WissKI als...': 'In relation to other research data management systems, I classify the quality of WissKI as...', + 'Wie wahrscheinlich ist es, dass Sie WissKI als Forschungsdaten-Management-System weiterempfehlen?':'How likely is it that you would recommend WissKI as a research data management system?' +} + +translate_csv('data/Community-Umfrage.csv', translation_dict) + +df = pd.read_csv('data/umfrage2survey.csv', encoding='utf8') +#df = pd.read_csv('data/Community-Umfrage.csv', encoding='utf8') + +plots = {} + +# Normal bar charts +# 1 Wie sind Sie auf WissKI aufmerksam geworden? +# 2 In welchem Bereich verwenden Sie WissKI? +# 25 Haben Sie Zugriff auf kompetenten IT- und Systemadministrationssupport innerhalb Ihres Projektes bzw. Institution? +# 26 Arbeitet Ihre Institution/ Unternehmen das erste Mal mit WissKI? + +bar_charts = [1,2,25,26] +for chart in bar_charts: + question_data = df.iloc[:, chart] + question_plot = bar_chart(question_data, question_data.name) + plots[chart] = (question_data.name, question_plot) + +# Cleaned pie charts +# 23 In welcher Rolle benutzen Sie WissKI? +question_data = df.iloc[:, 23] +for index, value in question_data.items(): + new_value = value.split(' (')[0] + question_data[index] = new_value + +question_plot = pie_chart(question_data, question_data.name) +plots[3] = (question_data.name, question_plot) + +# Normal Pie charts +# 3 Wie lange arbeiten Sie mit WissKI? +# 24 Haben Sie Erfahrung mit anderen Forschungsdaten-Management-Systemen? +# 27 Wie viele Stunden stehen Ihnen für die Arbeit mit WissKI wöchentlich zur Verfügung? +# 28 Welchen Community-Angeboten haben Sie mindestens einmal wahrgenommen? +pie_charts = [3,24,27,28] +for chart in pie_charts: + question_data = df.iloc[:, chart] + question_plot = pie_chart(question_data, question_data.name) + plots[chart] = (question_data.name, question_plot) + +# Point charts +# 9-22 Software Features +median_values = df.iloc[:, 9:23].median() +median_values_cleaned = pd.Series(name='Software Features') +for index, value in median_values.items(): + new_index = index.split(' [')[1].split(']')[0] + median_values_cleaned[new_index] = value + +point_plot = point_chart(median_values_cleaned, 'Software Features') +plots[9] = ('Software Features', point_plot) + + +# Bar charts with median +# 29 Im Verhältnis zu anderen Forschungsdaten-Management-Systemen verorte ich die Qualität von WissKI als... +bar_charts_with_median = [29] +for chart in bar_charts_with_median: + question_data = df.iloc[:, chart] + question_plot = bar_chart_with_special_legend(question_data, question_data.name, 'quality') + plots[chart] = (question_data.name, question_plot) + +bar_charts_with_median = [31] +for chart in bar_charts_with_median: + question_data = df.iloc[:, chart] + question_plot = bar_chart_with_special_legend(question_data, question_data.name, 'recommendation') + plots[chart] = (question_data.name, question_plot) + +plots = dict(sorted(plots.items(), key=lambda x: x[0])) + +# Generate list of charts +charts = [{'id': i+1, 'title': plots[col][0], 'data': plots[col][1]} for i, col in enumerate(plots.keys())] + +@app.route('/') +def index(): + return redirect(url_for('show_chart', chart_id=1)) + +@app.route('/chart/') +def show_chart(chart_id): + chart = next((c for c in charts if c['id'] == chart_id), None) + if not chart: + return redirect(url_for('index')) + + plot_url = chart['data'] + prev_id = chart_id - 1 if chart_id > 1 else len(charts) + next_id = chart_id + 1 if chart_id < len(charts) else 1 + + return render_template('chart.html', plot_url=plot_url, prev_id=prev_id, next_id=next_id, title=chart['title']) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/charts/__init__.py b/charts/__init__.py new file mode 100644 index 0000000..dd48f72 --- /dev/null +++ b/charts/__init__.py @@ -0,0 +1 @@ +# This file can be empty but is required to make the charts directory a package diff --git a/charts/__pycache__/__init__.cpython-312.pyc b/charts/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..cba5902 Binary files /dev/null and b/charts/__pycache__/__init__.cpython-312.pyc differ diff --git a/charts/__pycache__/bar_chart_from_stacked.cpython-312.pyc b/charts/__pycache__/bar_chart_from_stacked.cpython-312.pyc new file mode 100644 index 0000000..6c9c3c5 Binary files /dev/null and b/charts/__pycache__/bar_chart_from_stacked.cpython-312.pyc differ diff --git a/charts/__pycache__/chart_generator.cpython-312.pyc b/charts/__pycache__/chart_generator.cpython-312.pyc new file mode 100644 index 0000000..ef6cde0 Binary files /dev/null and b/charts/__pycache__/chart_generator.cpython-312.pyc differ diff --git a/charts/__pycache__/charts.cpython-312.pyc b/charts/__pycache__/charts.cpython-312.pyc new file mode 100644 index 0000000..926980c Binary files /dev/null and b/charts/__pycache__/charts.cpython-312.pyc differ diff --git a/charts/charts.py b/charts/charts.py new file mode 100644 index 0000000..ef2aa3c --- /dev/null +++ b/charts/charts.py @@ -0,0 +1,104 @@ +import seaborn as sns +import matplotlib.pyplot as plt +import io +import base64 +import pandas as pd + +def bar_chart(data, title): + data = data.str.split(';').explode().value_counts() + fig, ax = plt.subplots(figsize=(12,6)) + palette = sns.color_palette("husl", len(data)) + sns.barplot(x=data.index, y=data.values, ax=ax, hue=data.index, palette=palette, legend=False) + ax.set_xlabel('Answer') + ax.set_ylabel('Count') + + # Rotate the x-axis labels and set their horizontal alignment + for tick in ax.get_xticklabels(): + tick.set_rotation(45) + tick.set_horizontalalignment('right') + tick.set_fontsize(12) + + fig.tight_layout() + + img = io.BytesIO() + fig.savefig(img, format='png', dpi=300, bbox_inches='tight', pad_inches=0.5) + img.seek(0) + plot_url = base64.b64encode(img.getvalue()).decode('utf8') + plt.close() + return plot_url + +def bar_chart_with_special_legend(data, title, scale='recommendation'): + if scale == 'recommendation': + data = data.map({1:'not likely', 2:'less likely', 3:'not sure', 4:'more likely', 5:'definitely'}) + + # create a value counts series + data_counts = data.value_counts() + + fig, ax = plt.subplots(figsize=(12,6)) + palette = sns.color_palette("husl", 5) + sns.barplot(x=data_counts.index, y=data_counts.values, ax=ax, hue=data_counts.index, palette=palette) + ax.set_xlabel('Answer') + ax.set_ylabel('Count') + + # set y-axis to only have integer values + ax.yaxis.set_major_locator(plt.MultipleLocator(1.0)) + + # Rotate the x-axis labels and set their horizontal alignment + for tick in ax.get_xticklabels(): + tick.set_rotation(45) + tick.set_horizontalalignment('right') + tick.set_fontsize(12) + + fig.tight_layout() + + img = io.BytesIO() + fig.savefig(img, format='png', dpi=300, bbox_inches='tight', pad_inches=0.5) + img.seek(0) + plot_url = base64.b64encode(img.getvalue()).decode('utf8') + plt.close() + return plot_url + +def pie_chart(data, title): + data = data.str.split(';').explode().value_counts() + fig, ax = plt.subplots(figsize=(12,6)) + ax.pie(data.values, labels=data.index, autopct='%1.1f%%') + fig.tight_layout() + img = io.BytesIO() + fig.savefig(img, format='png', dpi=300, bbox_inches='tight', pad_inches=0.5) + img.seek(0) + plot_url = base64.b64encode(img.getvalue()).decode('utf8') + plt.close() + return plot_url + +def point_chart(data, title): + # Count the occurrences of each value + + # Map the x-axis values to the appropriate string + data = data.map({1:'not important', 2:'less important', 3:'important', 4:'more important', 5:'mandatory'}) + + # Create a figure and axis + fig, ax = plt.subplots() + + # Plot your data + for answer, value in data.items(): + ax.plot([value], [answer], marker='o') + + # Set the x-axis ticks and labels + ax.set_xticks(list(set(data.values))) + ax.set_xticklabels(list(set(data.values)), rotation=45) + + # Set the y-axis limits to remove the axis + ax.set_yticks(list(data.keys())) + + # Set the font size of the y-axis + for tick in ax.get_yticklabels(): + tick.set_fontsize(9) + + fig.tight_layout() + img = io.BytesIO() + fig.savefig(img, format='png', dpi=300, bbox_inches='tight', pad_inches=0.5) + img.seek(0) + plot_url = base64.b64encode(img.getvalue()).decode('utf8') + plt.close() + return plot_url + diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..0c13d88 --- /dev/null +++ b/static/styles.css @@ -0,0 +1,23 @@ +body { + font-family: Arial, sans-serif; + text-align: center; +} + +img { + width: 80%; + height: auto; +} + +div { + margin-top: 20px; +} + +a { + text-decoration: none; + font-size: 20px; +} + +.navigation { + display: flex; + justify-content: space-around; +} diff --git a/templates/chart.html b/templates/chart.html new file mode 100644 index 0000000..9e33141 --- /dev/null +++ b/templates/chart.html @@ -0,0 +1,34 @@ + + + + + + {{ title }} + + + + + +
+
+

{{ title }}

+ Chart +
+ +
+ + + +