{"id":27384265,"url":"https://github.com/mjanez/metadata-quality-stack","last_synced_at":"2026-04-16T05:03:16.055Z","repository":{"id":286642723,"uuid":"953100080","full_name":"mjanez/metadata-quality-stack","owner":"mjanez","description":"A comprehensive toolkit for analysing the quality of Open Data metadata. Based on the European Data Portal's Metadata Quality Assessment (MQA) methodology.","archived":false,"fork":false,"pushed_at":"2025-04-07T16:15:26.000Z","size":626,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-07T16:44:31.883Z","etag":null,"topics":["dcat-ap","dcat-ap-es","docker","fastapi","metadata","metadata-quality","mqa","nti-risp","open-data","rdf","shacl","streamlit"],"latest_commit_sha":null,"homepage":"https://mjanez.github.io/metadata-quality-stack/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mjanez.png","metadata":{"files":{"readme":"README.es.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-22T15:14:50.000Z","updated_at":"2025-04-04T15:34:18.000Z","dependencies_parsed_at":"2025-04-07T16:44:41.926Z","dependency_job_id":"7d2d521e-de67-4e5f-8baf-5fb5e9f79089","html_url":"https://github.com/mjanez/metadata-quality-stack","commit_stats":null,"previous_names":["mjanez/metadata-quality-stack"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjanez%2Fmetadata-quality-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjanez%2Fmetadata-quality-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjanez%2Fmetadata-quality-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjanez%2Fmetadata-quality-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mjanez","download_url":"https://codeload.github.com/mjanez/metadata-quality-stack/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248742421,"owners_count":21154488,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dcat-ap","dcat-ap-es","docker","fastapi","metadata","metadata-quality","mqa","nti-risp","open-data","rdf","shacl","streamlit"],"created_at":"2025-04-13T16:24:33.508Z","updated_at":"2026-04-16T05:03:16.048Z","avatar_url":"https://github.com/mjanez.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Metadata Quality Stack\n[![ES](https://img.shields.io/badge/lang-ES-yellow.svg)](README.es.md) [![EN](https://img.shields.io/badge/lang-EN-blue.svg)](README.md) [![Static Demo](https://img.shields.io/badge/demo-GitHub%20Pages-green.svg)](https://metadata-quality.mjanez.dev/)\n\nUn conjunto de herramientas completo para analizar la calidad de los metadatos de datos abiertos. Basado en la metodología de Evaluación de Calidad de Metadatos del Portal Europeo de Datos ([MQA](https://data.europa.eu/mqa/methodology?locale=en)) y en la validación mediante [SHACL](https://www.w3.org/TR/shacl/) para los perfiles [DCAT-AP](https://semiceu.github.io/DCAT-AP/), [DCAT-AP-ES](https://datosgobes.github.io/DCAT-AP-ES/) y [NTI-RISP (2013)](https://datosgobes.github.io/NTI-RISP/).\n\n## Inicio Rápido\n\n### **Prueba la versión React. ¡Es para la web!**\nPrueba la versión simplificada para navegador (**sin instalación**), más información en [react-app/README.md](react-app/README.md).\n\u003e [!TIP]\n\u003e **Demo en vivo**: [`metadata-quality.mjanez.dev/`](https://metadata-quality.mjanez.dev/)\n\u003e\u003cbr\u003e Esta edición se ejecuta completamente del lado del cliente e incluye el núcleo de MQA y el validador SHACL para comprobaciones instantáneas de calidad de metadatos en tu navegador.\n\n### **Despliegue completo con Docker** (Recomendado para validaciones más complejas)\nPara funcionalidades completas, incluyendo seguimiento histórico y acceso por API:\n```bash\ngit clone https://github.com/your-organization/metadata-quality-stack.git\ncd metadata-quality-stack\ndocker-compose up\n```\n\n## Visión General\n\nEsta herramienta ayuda a los publicadores y consumidores de datos a evaluar y mejorar la calidad de los metadatos en catálogos de datos abiertos. Analiza los metadatos frente a los principios [FAIR+C](https://www.ccsd.cnrs.fr/en/fair-guidelines/) (Findability, Accessibility, Interoperability, Reusability y Contextuality) y ofrece informes detallados sobre métricas de calidad.\n\n## Características\n\n### **Dos Opciones de Despliegue**\n1. **[Versión Estática](https://metadata-quality.mjanez.dev/)** - Compatible con GitHub Pages, sin backend\n2. **[Versión Docker](#installation)** - Con todas las funcionalidades, base de datos y API\n\n### **Capacidades Principales**\n- **Evaluación de Calidad**: Evalúa metadatos según la [metodología MQA](https://data.europa.eu/mqa/methodology?locale=en)\n- **Múltiples Perfiles**: Soporte para DCAT-AP, DCAT-AP-ES y NTI-RISP\n- **Validación en Tiempo Real**: Retroalimentación instantánea sobre la calidad de los metadatos\n- **Visualizaciones Interactivas**: Gráficos radar y desglose detallado de métricas\n- **Soporte Multilingüe**: Interfaces en inglés y español\n- **Integración API**: API REST para acceso programático (versión Docker)\n- **Seguimiento Histórico**: Almacena y visualiza la evolución de la calidad a lo largo del tiempo (versión Docker)\n- **Validación [SHACL](https://www.w3.org/TR/shacl/)**: Comprobación de cumplimiento con shapes oficiales de:\n   - **[DCAT-AP](https://github.com/SEMICeu/DCAT-AP)**: Estándar del portal de datos europeo\n   - **[DCAT-AP-ES](https://github.com/datosgobes/DCAT-AP-ES)**: Perfil nacional español  \n   - **[NTI-RISP](https://github.com/datosgobes/NTI-RISP)**: Estándar de interoperabilidad español\n\n\n### Versión Estática\n![React](/docs/img/react_app_1.png)\n![React](/docs/img/react_app_2.png)\n![React](/docs/img/react_app_3.png)\n![React](/docs/img/react_app_4.png)\n\n### Versión Docker\n![Home](/docs/img/app_1.png)\n![Home](/docs/img/app_2.png)\n![Home](/docs/img/app_3.png)\n![Home](/docs/img/app_4.png)\n![Home](/docs/img/app_5.png)\n![Home](/docs/img/openapi.png)\n\n## Arquitectura\n\n### **Opciones de Despliegue**\n\n#### **1. Versión Estática** (Solo cliente)\n- **Ubicación**: directorio [https://metadata-quality.mjanez.dev/](https://metadata-quality.mjanez.dev/)\n- **Tecnología**: HTML, CSS, TypeScript con [`N3.js`](https://github.com/rdfjs/N3.js), [`shacl-engine`](https://github.com/rdf-ext/shacl-engine), [`rdfxml-streaming-parser.js`](https://github.com/rdfjs/rdfxml-streaming-parser.js) y [React](https://es.react.dev/)  \n- **Despliegue**: GitHub Pages, cualquier hosting estático\n- **Características**: MQA y validación SHACL completas, visualización, sin backend requerido\n- **Caso de uso**: Despliegues rápidos, entornos de demostración, casos de uso puntuales\n\n#### **2. Versión Docker** (Full Stack)\n- **Tecnología**: Backend con FastAPI + frontend con Streamlit + proxy nginx\n- **Características**: Funcionalidad completa + base de datos + API + seguimiento histórico\n- **Caso de uso**: Entornos de producción, despliegues empresariales\n\nEl proyecto consta de los siguientes componentes principales:\n\n1. **API**: Backend basado en [FastAPI](https://fastapi.tiangolo.com/) que valida metadatos y genera informes\n2. **Frontend**: Interfaz web basada en [Streamlit](https://streamlit.io/) para visualizar informes\n3. **Versión Estática**: Implementación del lado del cliente para despliegue sencillo\n\n## Instalación\n\n### **Versión Estática** (Inicio rápido)\n\nUsando https://metadata-quality.mjanez.dev/ \n\n**Características**: Validación completa de metadatos, comprobación de conformidad SHACL con shapes oficiales, sin backend requerido.\n\n### **Versión Docker** (Producción)\n\nPara funcionalidad completa con base de datos y API:\n\n1. Clona el repositorio:\n    ```bash\n    git clone https://github.com/your-organization/metadata-quality-stack.git\n    cd metadata-quality-stack\n    ```\n\n2. Inicia los servicios con Docker Compose:\n    ```bash\n    docker-compose up\n    ```\n\n### **Instalación Manual**\n\n1. Clona el repositorio:\n    ```bash\n    git clone https://github.com/your-organization/metadata-quality-stack.git\n    cd metadata-quality-stack\n    ```\n\n2. Instala dependencias:\n    ```bash\n    pip install -e .\n    ```\n\n3. Inicia la API:\n    ```bash\n    uvicorn src.api.main:app --host 0.0.0.0 --port 8000\n    ```\n\n4. Inicia el frontend (en otra terminal):\n    ```bash\n    streamlit run src/frontend/app.py\n    ```\n\n## Uso\n\n### Backend (API)\nLa API ofrece los siguientes endpoints:\n\n- **API base**: `http://localhost:80/`\n- **Swagger UI**. Interfaz interactiva para probar la API: `http://localhost:80/docs`\n- **ReDoc**. Documentación detallada: `http://localhost:80/redoc`\n- **Endpoints**:\n   - `POST` `/validate`: Valida metadatos desde una URL\n   - `POST` `/validate-content`: Valida metadatos proporcionados directamente como contenido\n   - `GET` `/report/{url}`: Obtiene el informe más reciente para una URL\n   - `GET` `/history/{url}`: Obtiene el historial de informes para una URL\n   - `GET` `/reports/by-date`: Recupera informes dentro de un rango de fechas especificado\n   - `GET` `/reports/by-rating/{rating}`: Obtiene informes con una calificación de calidad específica\n\n### Frontend (Interfaz Web)\n\n- **Interfaz Web**: `http://localhost:8501/`\n- **Secciones principales**:\n   1. **Opciones de Validación**:\n       - Introducir una URL a un catálogo (soporta `RDF/XML`, `TTL`, `JSON-LD` y `N3`)\n       - Pegar contenido RDF directamente para validación\n       - Seleccionar distintos perfiles de conformidad ([DCAT-AP](https://interoperable-europe.ec.europa.eu/collection/semic-support-centre/dcat-ap), [DCAT-AP-ES](https://github.com/datosgobes/DCAT-AP-ES), [NTI-RISP](https://github.com/datosgobes/NTI-RISP))\n\n   2. **Funciones de Visualización**:\n       - Gráfico jerárquico que muestra la relación entre dimensiones y métricas\n       - Gráfico radar que muestra el rendimiento en las dimensiones [FAIR+C](https://data.europa.eu/mqa/methodology?locale=en)\n       - Desglose detallado de métricas con conteos y porcentajes\n\n   3. **Gestión de Informes**:\n       - Ver informes históricos y seguir la evolución de la calidad\n       - Exportar informes en formatos JSON y JSON-LD (vocabulario DQV)\n       - Gráficos de evolución de puntuaciones para seguimiento a largo plazo\n\n   4. **Panel de Analítica**:\n       - Estadísticas generales de los catálogos evaluados\n       - Distribución de calificaciones de calidad\n       - Comparación de medias por dimensión\n       - Catálogos mejor y peor evaluados\n       - Análisis de correlación entre dimensiones\n\n   5. **Soporte Multilingüe**:\n       - Alternar entre interfaces en inglés y español\n       - Descripciones y etiquetas de métricas localizadas\n\n## Desarrollo\n\nPara el desarrollo se recomienda usar VS Code con la configuración de Dev Container provista:\n\n1. Instala la extensión Remote - Containers de VS Code\n2. Abre el proyecto en VS Code\n3. Haz clic en \"Reopen in Container\" cuando se solicite\n4. Espera a que el contenedor se construya y configure\n\n### Traducción\nTras actualizar el archivo de traducción (`mqa.po`), no olvides compilarlo para generar el archivo `.mo`, por ejemplo para español:\n\n```sh\ncd metadata-quality-stack\n\n# Extraer textos i18n y actualizar el POT de las apps (p. ej. app.py)\nxgettext -d mqa --from-code=UTF-8 -o locales/mqa.pot src/frontend/app.py\n\n# Compilar archivos MO (Español)\nmsgfmt -o locale/es/LC_MESSAGES/mqa.mo locale/es/LC_MESSAGES/mqa.po\n``` \n\n## Extender las Métricas de Perfiles\n\nEl sistema está diseñado de forma modular, permitiendo añadir o personalizar métricas para perfiles específicos (DCAT-AP, DCAT-AP-ES, NTI-RISP, etc.). Sigue estos pasos para extender o crear métricas para un perfil:\n\n### 1. Define tus métricas en `config.py`\n\nCada métrica se define como un diccionario con ID, dimensión y peso. Para añadir métricas a un perfil nuevo o existente:\n\n```python\n# Define métricas específicas para tu perfil\nMY_PROFILE_SPECIFIC_METRICS = [\n      {\"id\": \"my_new_metric\", \"dimension\": \"interoperability\", \"weight\": 20},\n      {\"id\": \"another_metric\", \"dimension\": \"reusability\", \"weight\": 15}\n]\n\n# Añade tus métricas al diccionario METRICS_BY_PROFILE\nMETRICS_BY_PROFILE[\"my_profile\"] = COMMON_METRICS + MY_PROFILE_SPECIFIC_METRICS\n```\n\n### 2. Crea comprobadores para tus métricas en `validators.py`\n\nPara cada nueva métrica, crea un comprobador que implemente la lógica de validación:\n\n```python\n# Crea una clase checker si las existentes no encajan\nclass MyCustomChecker(MetricChecker):\n      def __init__(self, property_uri: URIRef):\n            self.property_uri = property_uri\n      \n      def check(self, g: Graph, resources: List[URIRef], context: Dict[str, Any] = None) -\u003e Tuple[int, int]:\n            # Implementa la lógica de comprobación aquí\n            # Retorna una tupla (count_successful, total)\n            return (count, total)\n\n# Añade tu checker al diccionario CHECKER_DEFINITIONS\nCHECKER_DEFINITIONS.update({\n      \"my_new_metric\": lambda: MyCustomChecker(MY_PROPERTY_URI),\n      \"another_metric\": lambda: ExistingCheckerClass(MY_OTHER_PROPERTY)\n})\n```\n\n### 3. Actualiza las puntuaciones por dimensión (si es necesario)\n\nSi añades métricas a una nueva dimensión, asegúrate de registrar la dimensión en el enum DimensionType en `models.py` y actualiza la función `calculate_dimension_scores` en `validators.py` para incluir la nueva dimensión.\n\n### 4. Registra tu perfil en el frontend (Opcional)\n\nPara que tu perfil sea seleccionable en la UI, actualiza el diccionario `PROFILES` en `frontend/config.py`:\n\n```python\nPROFILES = {\n      \"dcat_ap\": \"DCAT-AP 2.0\",\n      \"dcat_ap_es\": \"DCAT-AP-ES 2.0\",\n      \"nti_risp\": \"NTI-RISP\",\n      \"my_profile\": \"My Custom Profile\"\n}\n```\n\n### Ejemplo: Añadir un comprobador de formatos basado en etiquetas para NTI-RISP\n\nAquí un ejemplo de extensión de NTI-RISP con un comprobador que valida etiquetas frente a un vocabulario CSV:\n\n1. Crea la clase checker especializada:\n\n```python\nclass VocabularyLabelComplianceChecker(MetricChecker):\n      \"\"\"Check if property labels comply with a CSV-based vocabulary.\"\"\"\n      \n      def __init__(self, property_uris: List[URIRef], csv_path: str, \n                         compare_column: str = None, label_property: URIRef = RDFS.label):\n            self.property_uris = property_uris\n            self.csv_path = csv_path\n            self.compare_column = compare_column\n            self.label_property = label_property\n            # Initialize allowed values from CSV file\n            # ...\n      \n      def check(self, g: Graph, resources: List[URIRef], context: Dict[str, Any] = None) -\u003e Tuple[int, int]:\n            # Check values against the allowed values, considering labels\n            # ...\n```\n\n2. Añádelo a `CHECKER_DEFINITIONS`:\n\n```python\nCHECKER_DEFINITIONS.update({\n      \"dct_format_nonproprietary_nti\": lambda: VocabularyLabelComplianceChecker(\n            [DCTERMS.format], MQA_VOCABS['non_proprietary']\n      )\n})\n```\n\n3. Añade la métrica a `NTI_RISP_SPECIFIC_METRICS`:\n\n```python\nNTI_RISP_SPECIFIC_METRICS.append(\n      {\"id\": \"dct_format_nonproprietary_nti\", \"dimension\": \"interoperability\", \"weight\": 25}\n)\n```\n\n## Actualizar el Certificado SSL\nPara actualizar el certificado SSL local, sigue estos pasos:\n\n1. Genera un nuevo certificado y clave privada:\n```sh\nopenssl req -x509 -nodes -days 365 -newkey rsa:2048 \\\n   -keyout nginx/setup/metadata-quality-stack.key \\\n   -out nginx/setup/metadata-quality-stack.crt \\\n   -subj \"/C=ES/ST=Madrid/L=Madrid/O=Development/CN=localhost\"\n```\n\n2. Verifica que los archivos se hayan creado correctamente:\n```sh\nls -l nginx/setup/metadata-quality-stack.*\n```\n\n3. Reinicia el contenedor `nginx` para aplicar los cambios:\n```sh\ndocker compose restart nginx\n```\n\n\u003e [!CAUTION]\n\u003e Este certificado es solo para desarrollo local. En producción, utiliza un certificado válido emitido por una autoridad certificadora.\n\n## Licencia\n\nConsulta el archivo [LICENSE](/LICENSE) para los derechos y limitaciones de la licencia (MIT).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjanez%2Fmetadata-quality-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmjanez%2Fmetadata-quality-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjanez%2Fmetadata-quality-stack/lists"}