Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add report process #2

Merged
merged 8 commits into from
Apr 12, 2024
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
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11"]
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v4
Expand All @@ -32,8 +32,8 @@ jobs:
run: make test
- name: Lint with flake8 ⚙️
run: make lint
if: matrix.python-version == 3.7
if: matrix.python-version == 3.9
- name: Build docs 🏗️
run: make docs
if: matrix.python-version == 3.7
if: matrix.python-version == 3.9

54 changes: 41 additions & 13 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,59 @@
"sphinx.ext.todo",
"sphinx.ext.viewcode",
"IPython.sphinxext.ipython_console_highlighting",
"nbsphinx",
# "nbsphinx",
"pywps.ext_autodoc",
]

# To avoid having to install these and burst memory limit on ReadTheDocs.
# List of all tested working mock imports from all birds so new birds can
# inherit without having to test which work which do not.
autodoc_mock_imports = [
"numpy", "xarray", "fiona", "rasterio", "shapely",
"osgeo", "geopandas", "pandas", "statsmodels",
"affine", "rasterstats", "spotpy", "matplotlib",
"scipy", "unidecode", "gdal", "sentry_sdk", "dask",
"numba", "parse", "siphon", "sklearn", "cftime",
"netCDF4", "bottleneck", "ocgis", "geotiff", "geos",
"hdf4", "hdf5", "zlib", "pyproj", "proj", "cartopy",
"scikit-learn", "cairo"
"numpy",
"xarray",
"fiona",
"rasterio",
"shapely",
"osgeo",
"geopandas",
"pandas",
"statsmodels",
"affine",
"rasterstats",
"spotpy",
"matplotlib",
"scipy",
"unidecode",
"gdal",
"sentry_sdk",
"dask",
"numba",
"parse",
"siphon",
"sklearn",
"cftime",
"netCDF4",
"bottleneck",
"ocgis",
"geotiff",
"geos",
"hdf4",
"hdf5",
"zlib",
"pyproj",
"proj",
"cartopy",
"scikit-learn",
"cairo",
]

# Monkeypatch constant because the following are mock imports.
# Only works if numpy is actually installed and at the same time being mocked.
#import numpy
#numpy.pi = 3.1416
# import numpy
# numpy.pi = 3.1416

# We are using mock imports in readthedocs, so probably safer to not run the notebooks
nbsphinx_execute = 'never'
nbsphinx_execute = "never"

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
Expand Down Expand Up @@ -112,7 +140,7 @@
todo_include_todos = False

# Suppress "WARNING: unknown mimetype for ..." when building EPUB.
suppress_warnings = ['epub.unknown_project_files']
suppress_warnings = ["epub.unknown_project_files"]

# Avoid "configuration.rst:4:duplicate label configuration, other instance in configuration.rst"
autosectionlabel_prefix_document = True
Expand Down
1 change: 0 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

installation
configuration
notebooks/index
dev_guide
processes
authors
Expand Down
48 changes: 0 additions & 48 deletions docs/source/notebooks/example.ipynb

This file was deleted.

8 changes: 0 additions & 8 deletions docs/source/notebooks/index.rst

This file was deleted.

11 changes: 10 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@ channels:
dependencies:
- pip
- python>=3.8,<3.12
- pywps>=4.5.1,<4.6
- pywps>=4.5.2,<4.7
- jinja2
- click
- psutil
# tests
- pytest
# provenance
- prov>=2.0.0
- pydot
- graphviz
- rdflib
- rdflib-sqlalchemy
- sqlalchemy<2
- pandas
- pyyaml
41 changes: 41 additions & 0 deletions parrot/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from rdflib import Graph, URIRef
from rdflib.plugins.sparql import prepareQuery

from pywps import configuration

# Provide the path to the SQLite database in the local folder
# DB_URL = configuration.get_config_value("provenance", "db_url")
DB_URL = configuration.get_config_value("logging", "database")


class GraphDB(object):
def __init__(self):
# Create a graph with a specific backend store
self.graph = Graph(
store="SQLAlchemy", identifier=URIRef("http://example.org/graph")
)
self.graph.open(DB_URL, create=True)

def add(self, data):
new_graph = Graph()
new_graph.parse(data=data, format="turtle")

# add rdf to existing graph
for triple in new_graph:
self.graph.add(triple)
# Commit changes to the store
self.graph.commit()

def query(self, query_str):
namespaces = {
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"foaf": "http://xmlns.com/foaf/0.1/",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"prov": "http://www.w3.org/ns/prov#",
"provone": "http://purl.dataone.org/provone/2015/01/15/ontology#",
"dcterms": "http://purl.org/dc/terms/",
"clint": "urn:clint:",
}
query = prepareQuery(query_str, initNs=namespaces)
results = self.graph.query(query)
return results
2 changes: 2 additions & 0 deletions parrot/processes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .wps_say_hello import SayHello
from .wps_dashboard import Dashboard

processes = [
SayHello(),
Dashboard(),
]
102 changes: 102 additions & 0 deletions parrot/processes/wps_dashboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from pathlib import Path

from pywps import Process, LiteralInput, ComplexOutput, Format

from parrot import query


class Dashboard(Process):
def __init__(self):
inputs = [
LiteralInput(
"time",
"Time Period",
abstract="The time period for the report seperated by /"
"Example: 2023-09-01/2023-09-30",
data_type="string",
default="2023-09-01/2023-09-30",
min_occurs=0,
max_occurs=1,
),
]
outputs = [
ComplexOutput(
"report",
"Generated HTML Report",
as_reference=True,
supported_formats=[Format("text/html")],
),
]

super(Dashboard, self).__init__(
self._handler,
identifier="dashboard",
title="Generate HTML Report",
version="1.0",
abstract="Generate an HTML report from a provenance database.",
inputs=inputs,
outputs=outputs,
status_supported=True,
store_supported=True,
)

def _handler(self, request, response):
workdir = Path(self.workdir)
# input_csv = request.inputs['input_csv'][0].file

# Query the provenance database ... result is a Pandas DataFrame
df = query.query()

# Generate an HTML report from the DataFrame
html_report = self.write_html(df, workdir)

print(f"report: {html_report}")
response.outputs["report"].file = html_report
# response.outputs["report"].output_format = Format("text/html")

return response

def write_html(self, df, workdir):
# Convert the DataFrame to an HTML table
html_table = df.to_html(escape=False, index=False)

# Define the HTML template
html_template = f"""
<!DOCTYPE html>
<html>
<head>
<title>Provenance Report</title>
<style>
table {{
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
}}

th, td {{
text-align: left;
padding: 8px;
}}

th {{
background-color: #f2f2f2;
}}

tr:nth-child(even) {{
background-color: #f2f2f2;
}}
</style>
</head>
<body>
<h1>Provenance Report</h1>
{html_table}
</body>
</html>
"""

# Write the HTML template to a file
outfile = workdir / "provenance_report.html"
with outfile.open(mode="w") as file:
file.write(html_template)

return outfile
Loading