Jekyll2023-10-28T07:47:16+00:00https://sigdeletras.com/feed.xmlSIGdeletras :: Tecnologías de Información GeográficaPágina web de Patricio Soriano. SIGdeletras. Tecnologías de Información GeográficaPatricio Soriano Castropasoriano@sigdeletras.comLanzanda versión 2 del plugin de QGIS Spanish Inspire Catastral Downloader y algunas reflexiones despues de 6 años.2023-10-27T00:00:00+00:002023-10-27T00:00:00+00:00https://sigdeletras.com/2023/lanzanda-version-2-del-plugin-de-qgis-spanish-inspire-catastral-downloader-y-algunas-reflexiones-despues-de-6-a%C3%B1os<p>Ya se encuentra disponible en el <a href="https://plugins.qgis.org/plugins/Spanish_Inspire_Catastral_Downloader/">repositorio oficial del complementos de QGIS</a> la versión 2.0 del complemento <strong>Spanish Inspire Catastral Downloader (SICD)</strong>.
<!--more--></p>
<p>El objetivo de este desarrollo es el de facilitar a los usuarios de QGIS la descarga por municipios de los <a href="https://www.catastro.minhap.es/webinspire/index.html">datos cartográficos del catastro INSPIRE de España</a>. Para más información se puede leer esta <a href="https://sigdeletras.com/2017/blog/plugin-de-qgis-para-descarga-de-datos-catastrales-inspire/">entrada sobre el plugin</a> escrita en 2017.</p>
<p>La principal novedad de esta nueva versión es la corrección de un error existente derivado en las diferencias en los nombres de los municipios de un listado interno del complemento. Estos datos se usaban para crear la URL de descarga. En origen, el listado se hizo a mano según los datos de Catastro. En ocasiones se producían fallos por diferencias en las denominaciones (uso de acentos, cedillas, eliminación de preposiciones…) por lo que la dirección URÑ del servicio ATOM no era la correcta.</p>
<p>La solución ha venido de la mano de la desarrolladora <a href="https://www.linkedin.com/in/lgarciademarina/">Laura García de Marina</a>. Laura ha incorporado el código Python para usar de los datos JSON procedentes de la <a href="https://www.catastro.meh.es/ayuda/servicios_web.htm">REST API de Catastro</a> con los listados provincias, municipios y códigos usados por la Dirección General de Catastro. Los listados son presentados en formulario principal para configurar la URL correcta de descarga de los archivos ZIP con las capas GML catastrales por municipio.</p>
<p>Quiero agradecer sinceramente el aporte de Laura e indicar el interés de otros complementos desarrollados por ella como <a href="https://github.com/lgarciademarina/catastro_historia">Catastro con Historia</a> que permite visualizar las series temporales del WMS de Catastro en QGIS o la extensión para Chrome “ATOM Catastro España” para la descarga de conjuntos de datos predefinidos de Catastro por municipios.</p>
<p>Tras la revisión e integración de los cambios del <em>pull request</em> he aprovechado para incluir estos cambios:</p>
<ol>
<li>He eliminado el código que permitía el uso del complemento en versiones 2.* de QGIS. No creo que ya sea necesario.</li>
<li>El flujo del complemento se divide en dos: la descarga de los datos y la carga de las capas en el proyecto QGIS activo.</li>
<li>Han sido añadidas mejoras respecto a los avisos y comunicación con el usuario, tanto en la barra de mensajes como en el panel de avisos.</li>
<li>Los procesos del complemento han sido acelerados al eliminar la conversión a GeoJSON de los datos GML. Las versiones actuales de QGIS cargan ya sin problema los datos en este formato.</li>
<li>Al cargar en el proyecto activo, los GMLs son agrupados en el panel de capas con el código INE y el nombre del municipio según Catastro.</li>
<li>Tanto los mensajes de aviso como el formulario están completamente traducidos en español e inglés. No costaría mucho traducirlo a otras lenguas cooficiales o idiomas.</li>
<li>Se han realizados ciertas revisiones y mejoras en el estilo de código Python del complemento. He dudado en realizar una refactorización del código e incluir una clase con toda la lógica que no depende de QGIS. Pero lo dejaré para más adelante (…miento)</li>
</ol>
<h2 id="impacto-en-internet-del-complemento-después-de-6-años-de-su-lanzamiento">Impacto en Internet del complemento después de 6 años de su lanzamiento</h2>
<p>La valoración general del lanzamiento del complemento allá por el 2017 (<em>tempus fugit</em> que diría el otro) no puede ser más que positiva. El complemento ha tenido en el momento de escritura de esta descarga más de ¡60.000 descargas! Parafraseando a la gran Lola Flores: …si un euro me diera cada usuario por la descarga… En fin, esto es sin duda lo de menos. Sinceramente me parece impresionante para tratarse de un desarrollo pensado para usuarios de España.</p>
<p>La difusión del complemento en blog y redes sociales también ha sido grande a mi entender. Yo mismo <a href="https://sigdeletras.com/presentaciones/accediendo-a-datos-abiertos-con-qgis-un-par-plugins-de-ejemplo-geocamp-es-2017-almeria/">presenté el complemento en Geocamp ES 2017 Almería</a></p>
<p>Empresas como <a href="https://geoinnova.org/blog-territorio/descarga-de-cartografia-catastral-en-qgis-mediante-el-plugin-spanish-inspire-catastral-downloader/">Geoinnova</a>, <a href="https://mappinggis.com/2021/06/mapas-de-usos-del-suelo-y-de-evolucion-urbana-con-qgis/">MappingGIS</a> o <a href="https://www.cursosgis.com/plugin-spanish-inspire-catastral-downloader-para-qgis/">TYC GIS</a> cuentan con entradas en sus blog donde se explica su uso y manejo. En blogs de impacto como <a href="https://zonegis.es/tag/spanish-inspire-catastro-downloader/">ZoneGIS</a>, <a href="https://www.cartografiadigital.es/2017/09/cartografia-catastral-en-qgis.html">Cartografía Digital</a>, <a href="https://www.gisandbeers.com/descarga-de-cartografia-catastral-plugin-qgis/">GISandBeers</a> del gran Roberto Matellanes o <a href="https://www.geomapik.com/uncategorized/como-descargar-informacion-catastral-parcelas-edificios-qgis/">Geomapik</a> hay textos sobre el plugin o referencias de su uso en trabajos que necesitan la explotación de datos catastrales.</p>
<p>Tengo menos controlado las referencias al complemento en publicaciones científicas como esta [<a href="https://www.researchgate.net/publication/371774517_Clasificador_Catastral_complemento_de_QGIS_para_la_clasificacion_de_los_usos_del_suelo_urbano_a_nivel_de_parcela">1</a>] o incluso Trabajos Fin de Máster como [<a href="https://openaccess.uoc.edu/bitstream/10609/132129/7/flimasTFM0621memoria.pdf">2</a>] y [<a href="https://gredos.usal.es/handle/10366/143982?locale-attribute=en">3</a>]. Me gustaría poder conocer algunas más, pero esto es complicado a no ser que alguien me lo comente.</p>
<p>Me llamó mucho la atención que en el libro <a href="https://www.ra-ma.es/libro/qgis-aplicado-al-urbanismo_118815/">QGIS Aplicado al Urbanismo</a> de Rafael Ramón Temes y Alfonso Moya publicado por Ra-Ma en 2021 exista un apartado sobre el complemento.</p>
<p>Hay dos citas relacionadas que me sorprendieron bastante. La primera de ellas fue la que se hizo en el apartado de metodologías de un artículo publicado por <strong>El Confidencial</strong> titulado <a href="https://www.elconfidencial.com/vivienda/2019-11-26/mapa-espana-urbanismo-edificios-historia_2348415/">‘¿De qué año es tu casa? El mapa que muestra cómo se ha construido España’</a>. La segunda estaba en una entrada <a href="https://www.xataka.com/magnet/envejecimiento-ciudades-espanolas-ilustrado-estos-mapas-a-traves-sus-edificios">El envejecimiento de las ciudades españolas, ilustrado en estos mapas a través de sus edificios</a> del conocido blog de tecnología <strong>Xataka</strong>.</p>
<p>Casi recién publicado el complemento, técnicos de Dirección General de Catastro hicieron una comunicación en las <a href="https://www.idee.es/resources/presentaciones/JIIDE17/Apresentacoes_JIIDE2017_Conjunto_datos_edificios_BU_en_la_Direccion_General_del_Catastro_Pablo_Gomez_Dominguez.pdf">Jornadas Ibéricas de IDE (JIDEE) de 2017</a>. La ponencia trataba sobre el Conjunto de Datos de Edificios (BU) en la Dirección General. En una de las láminas de la presentación se mostraba el complemento SICD como ejemplo de explotación de estos datos catastrales sobre construcciones. He llegado a recibir correos hasta de técnicos de catastro haciéndome alguna consulta. Seguro que a ellos también le han dado la brasa en algún momento preguntando sobre el complemento 😅.</p>
<p>Hay varios cursos que incorporan en su temario un apartado sobre el desarrollo. Mis compañeros de Geoinnova dan formación en un curso titulado <a href="https://geoinnova.org/curso/gestion-catastral-catastro-sig/">Curso de especialización en Gestión Catastral con QGIS</a> donde se usa profusamente el complemento. Me resultó llamativo que la <a href="https://www.youtube.com/watch?v=Wxj5WBT9xnY">Universitat Politècnica de València</a> tuviera un vídeo explicativo en YouTube sobre el manejo de la herramienta de QGIS en uno de sus <em>mooc</em> ya que fue algo que nunca llegué a hacer.</p>
<h2 id="experiencias-personales">Experiencias personales</h2>
<p>Mucho ha llovido desde que en 2017 se lanzó este complemento. En esos años me encontraba en plena transformación profesional que me ha llevado de aplicar los SIG a estudios de territorios prehistóricos, pasando por diseño e implantación dentro de administraciones públicas, a tener la suerte de coordinar hoy en día el <a href="https://geoinnova.org/consultoria-desarrollo-sistemas-de-informacion-geografica/">Área de Desarrollo y SIG de Geoinnova</a>.</p>
<p>Desde ya más tres años y medio, y gracias a la oportunidad que me brindó Luis Quesada, trabajo codo con codo con un estupendo equipo de profesionales que ponen su máximo interés y esfuerzo en aportar soluciones tecnológicas a empresas y profesionales que necesitan trabajar con datos geográficos.</p>
<p>Sigo usando a diario QGIS, definiendo y desarrollando plugins y usando Python en muchos de mis procesos. Al volver al revisar el código en esta nueva versión, <strong>ha sido inevitable detectar errores de principiante</strong>: posibilidades de refactorizar el complemento, aplicar los conocimientos (POO) y buenas prácticas (testing) que sigo aprendiendo a diario.</p>
<p>A pesar de todo esto, creo que lo realmente importante del complemento, como creo que me comentó alguien en su momento, fue <strong>la idea</strong>: reaprovechar un recurso abierto, hacerlo accesible e integrarlo en una herramienta tan potente como QGIS.</p>
<p>Gracias a este complemento he podido aprender lo que conlleva, tanto de bueno como de malo, el <strong>desarrollo de un programa de código abierto</strong>. En general la experiencia ha sido bastante positiva. Que gente que no conoces de nada te agradezca que hagas abierto y accesible tu trabajo es realmente enriquecedor.</p>
<p>Por otro lado, no han sido ni una ni dos las veces que algún usuario se ha enfadado porque no he contestado de forma inmediate sus correos. En alguna ocasiones, casi me han llegado a exigir que arreglara su problema como si fueran clientes que hubieran pagado el desarrollo (me viene otra vez a la cabeza Lola Flores).</p>
<p>A pesar de estos últimos detalles sin importancia, creo que la creación del complemento Spanish Inspire Catastral Downloader ha sido una <strong>experiencia enriquecedora</strong> profesional y personalmente. Es más, siempre que he podido intentado repetirla con otros complementos o desarrollos.</p>
<p>Recomiendo a todas aquellas personas que quieran adentrarse en este mundo de la ‘geo’ programación que se lancen, se prueben y compartan sus trabajos con la comunidad.</p>Patricio Soriano Castropasoriano@sigdeletras.comYa se encuentra disponible en el repositorio oficial del complementos de QGIS la versión 2.0 del complemento Spanish Inspire Catastral Downloader (SICD).Project Reports. Complemento de QGIS para generar informes de proyectos2023-01-08T00:00:00+00:002023-01-08T00:00:00+00:00https://sigdeletras.com/2023/project-reports-complemento-de-qgis-para-generar-informes-de-proyectos<p><strong>Project Reports</strong> es un nuevo complemento pensado para recopilar información y propiedades de diferentes objetos de proyectos de QGIS, como capas, campos o composiciones y generar archivos de datos abiertos (CSV y HTML) con esta información.
<!--more--></p>
<p><img src="/images/blog/202301-project_reports/project_reports_qgis_plugin.png" alt="QGIS Plugin Project Reports" /></p>
<h2 id="objetivos">Objetivos</h2>
<p>El desarrollo de este sencillo plugin de QGIS viene marcado por la necesidad de generar de forma rápida los metadatos vinculados sobre proyectos QGIS.</p>
<p>Estos metadatos son una parte fundamental de cualquier proyecto profesional. <strong>Disponer y ofrecer una documentación de calidad debe ser considerado como un elemento diferenciador</strong>.</p>
<p>Como en otros <em>“side projects”</em> anteriores, el desarrollo tiene un grupo de objetivos personales y formativos. En esta ocasión, los puntos que han guiado este trabajo han sido los siguientes:</p>
<ul>
<li>Potenciar las opciones de la Programación Orientada a Objetos (POO) en Python mediante la creación de una <strong>clase Python denominada QProjectReport</strong> que almacene os atributos y métodos necesarios para su posterior importación y uso en el desarrollo propio de la GUI del complemento.</li>
<li>Escritura de código intentando aplicar al máximo la <a href="https://peps.python.org/pep-0008/">guía de estilos de Python (PEP 8)</a></li>
<li>Añadir la documentación (docstrings) del código Python.</li>
<li>Generar la <a href="https://github.com/sigdeletras/project-reports-qgis-plugin/blob/master/README.md">información asociada el proyecto</a> en inglés</li>
</ul>
<h2 id="instalación-y-uso">Instalación y uso</h2>
<p>El <strong>plugin</strong>** se encuentra disponible en el <a href="https://plugins.qgis.org/plugins/project_report/">repositorio oficial de complementos de QGIS</a> y puede instalarse desde QGIS.</p>
<p>Una vez instalado, el complemento es accesible desde el menú de complementos o desde la barra de herramientas.</p>
<p><img src="/images/blog/202301-project_reports/menu_toolbar.png" alt="Menu and toobar" /></p>
<p>Tras la activación, el complemento presenta unas opciones de configuración obligatorias partir de las cuales se creará los informes CSV o/o HTML correspondientes:</p>
<p><img src="/images/blog/202301-project_reports/main_form.png" alt="Main form" /></p>
<ul>
<li><strong>Output directory</strong>. Carpeta de salida donde se generará la estructura de carpetas para los informes. La carpeta principal tendrá el nombre del proyecto.</li>
<li><strong>Objects</strong>. La información recopilada corresponde con datos sobre el proyecto (título, nombre del fichero, crs…), las capas geográficas cargadas (nombre, tipo de capa, tipo de geometría…), los campos de las capas vectoriales (nombre del campo, tipo, alias…) y las composiciones gráficas (nombre, tipo, atlas…). La información es obtenida de distintas clases de PyQGIS (QgsProject, QgsFields, QgsLayoutManager…) El listado completo de campos está disponible en el repositorio de <a href="https://github.com/sigdeletras/project-reports-qgis-plugin/blob/master/README.md">GitHub</a></li>
<li><strong>Output formats</strong>. Los formatos disponibles son CSV (una por cada tipo de objeto) y HTML. Es posible personalizar la hoja de estilos CSS del HTML editando la variable <em>CSS</em> existente en el fichero de la clase (QProjectReport.py)</li>
</ul>
<p><img src="/images/blog/202301-project_reports/html_report.png" alt="HTML" /></p>
<p><img src="/images/blog/202301-project_reports/csv.png" alt="CSV" /></p>
<h2 id="comentarios-aportes-y-contribuciones">Comentarios, aportes y contribuciones</h2>
<p>Todo es mejorable y por eso el complemento está abierto contribuciones. Por ejemplo, creo que sería interesante poder añadir datos sobre los formularios, tablas relacionadas o incorporar la opción de salida para hojas de cálculo.</p>
<p>Para aportes de código he añadido esta guía para <a href="https://github.com/firstcontributions/first-contributions">“Primeras contribuciones”</a> de Github. Y para comentarios y aportes nada mejor que usar el sistema de <a href="https://github.com/sigdeletras/project-reports-qgis-plugin/issues">issues</a>.</p>
<p>Un geosaludo 🖐 y ¡¡Feliz 2023!!</p>Patricio Soriano Castropasoriano@sigdeletras.comProject Reports es un nuevo complemento pensado para recopilar información y propiedades de diferentes objetos de proyectos de QGIS, como capas, campos o composiciones y generar archivos de datos abiertos (CSV y HTML) con esta información.El efecto mariposa o sobre la gestión de un error en PyQGIS y QGIS2022-07-10T00:00:00+00:002022-07-10T00:00:00+00:00https://sigdeletras.com/2022/el-efecto-mariposa-o-sobre-errores-de-pyqgis-y-qgis<p>Como se suele decir “hasta de los errores se aprende”. Esta entrada me sirve para recopilar, organizar y exponer un conjunto de lecciones aprendidas durante el proceso de corrección de un error. Un error informático, en concreto de programación en un complemento de QGIS usando <a href="https://qgis.org/pyqgis/3.0/">PyQGIS</a>, la API para Python de este potente GIS.
<!--more--></p>
<p>La solución final no fue compleja, solo hubo que introducir un paso intermedio en un modelo de procesamiento de QGIS. Pero tirando de nuevo de tópico, aquí “lo importante fue el camino y no el destino (la solución)”. En este artículo se recopilan algunas de estas experiencias aprendidas durante ese y otros ‘caminos’.</p>
<p><img src="/images/blog/202207-mariposa/The_Butterfly_Effect.jpeg" alt="" /></p>
<p><em>Fuente: Wikipedia</em></p>
<h2 id="documentación-de-código-y-naming">Documentación de código y naming</h2>
<p>Es clave poder contar con los documentos que se hayan generado antes y después de la programación: casos de usos, diagramas ER, modelos, diagramas de flujo, control de cambios… Si no existen, por la razón que sea, por ejemplo por ser un desarrollo heredado, hay que ir generándolo a medida que vamos conociendo el código.</p>
<p>Que el <strong>código esté bien documentado</strong> es fundamental. Dedicarle tiempo y mimo añadir los <a href="https://en.wikipedia.org/wiki/Docstring">docstring</a> de las clases y funciones nos va a ser muy útil cuando tengamos que consultarlo después de algún tiempo. Aunque si nos ponemos puristas, un buen código se describe a sí mismo, dependiendo de nuestra experiencia es interesar ir dejando comentarios concretos que ayuden a comprender mejor la aplicación.</p>
<p>Otro gran recurso será en la <strong>elección correcta de los nombres de variables y funciones</strong>. Hay toneladas de literatura sobre esto, véase por ejemplo el libro <a href="https://archive.org/details/cleancodercodeof0000mart">The Clean Coder de Robert C. Martin</a>, pero pongo un sencillo ejemplo. Si tengo una variable que representa a una capa puntual de acometidas y la llamo <em>layer</em>, no pasará nada, siempre que trabaje solo con una capa. Pero ¿qué corre si tengo 2 o n capas?,¿las llamaremos <em>layer_2</em>, <em>layer_3</em> o <em>layer_n</em>?¿cómo sabré a qué corresponde <em>layer_20</em>?</p>
<p>Una (mala) solución sería tirar de comentarios dentro del texto explicando que <em>layer_20</em> corresponde con una capa de transformadores y así sucesivamente. Pero si al declarar la variable directamente usamos el nombre <em>layer_transformers</em> tendremos este tema resuelto.</p>
<p>La máxima debe ser usar <strong>nombres intencionados y descriptivos, evitar abreviaciones, prefijos o el uso de secuencias de números en variables</strong>. Además de esto es importante no perder de vista las convicciones sobre los nombre definidas en la <a href="https://peps.python.org/pep-0008/#naming-conventions">PEP8 de Python</a></p>
<h2 id="entornos-y-versiones">Entornos y versiones</h2>
<p>Tener <strong>control sobre las versiones de los paquetes, librerías y programas</strong> que vamos a usar para nuestro desarrollo es fundamental.</p>
<p>Cuando trabajamos exclusivamente con librerías, nos protegemos de estos cambios creando <a href="https://docs.python.org/es/3/tutorial/venv.html">entornos virtuales</a> donde definimos las versiones a usar. Pero al usar un programa como QGIS, esta rutina no nos asegura que todo vaya a funcionar correctamente. Este SIG de código abierto cuenta con muchas más funcionalidades que no dependen exclusivamente de su API. Un ejemplo claro es la incorporación de geoprocesos de SAGA o GRASS.</p>
<p>Ahí va otro ejemplo, que puede traernos algún que otro problema. Partimos de un complemento de QGIS que integra la ejecución de modelos de procesamiento. El usuario final trabaja con una versión LTR de QGIS (3.10) dentro de un Amazon WorkSpace. Es lo que se llama su entorno de producción. Como versión de pruebas, tenemos otro workSpace pero en esta ocasión con QGIS 3.16. Y para rematar, nuestro equipo de trabajo en local tiene la última versión LTR de QGIS 3.22.</p>
<p>Esta multitud de versiones nos puede dar verdaderos dolores de cabeza ya que para cada nuevo lanzamiento, siempre se incorporan mejoras y correcciones que pueden afectar a nuestro código. Aunque toda la documentación sobre los <a href="https://www.qgis.org/en/site/forusers/visualchangelogs.html">cambios es recopilada en la página del proyecto QGIS</a> tendemos a quedarnos en los apartados de novedades. Pero como desarrolladores es igual de relevante ir al final del registro de cambios y estar atentos al último apartado de <em>Notable Fixes</em>.</p>
<p>Esto produce que un cambio, entendido como cambio el uso de alguna clase de PyQGIS o incluso de algún geoproceso, no funcione correctamente en versiones estables más antiguas. Debemos siempre programar en la misma versión que va a usar el usuario final.</p>
<p>Si en algún momento se produce la necesidad de cambiar de versión, por ejemplo para implementar una nueva nueva funcionalidad, debemos asegurarnos que todo nuestro desarrollo previo se va poder ejecutar en la versión a migrar y que el <strong>costo (tiempo, recurso, dinero…) de este cambio nos es beneficioso</strong>.</p>
<h2 id="implantar-un-sistema-de-logs-y-avisos">Implantar un sistema de logs y avisos</h2>
<p>Cuando estamos trabajando en nuestro propio equipo y se produce algún tipo de error siempre tenemos a mano la información que nos ofrece el terminal donde estamos ejecutando el código, el editor (Vscode) o framework (PyCharm) que manejemos o el mismo QGIS mediante los paneles de mensajes.</p>
<p>Pero <strong>¿cómo saber qué ha pasado el equipo del cliente-usuario donde se ha producido el error?</strong> Si no tenemos implementadas herramientas internas (logs) y externas (ventanas de información) tendremos que dedicar mucho más tiempo del deseado en que el cliente nos explique no solo lo que ha pasado, sino también qué es lo que ha hecho (partiendo del hecho de que seguramente él no ha tocado nada).</p>
<p>QGIS nos ofrece clases para poder desarrollar ventanas emergentes que comuniquen al usuario cómo va evolucionando un determinado procesos, si se ha concluído con éxito o si algo ha fallado.</p>
<p>Es fundamental también el <strong>registro de estos eventos</strong> usando archivos de registros o <a href="https://es.wikipedia.org/wiki/Log_(inform%C3%A1tica)">logs</a>. En este historial queda constancia temporal de los procesos realizados inclusos de su tipo o categoría (info, warnings, errors…) Su utilidad está más que clara. En esta <a href="https://sigdeletras.com/2021/comunicacion-con-el-usuario-y-logging-para-plugins-de-qgis/">entrada pasada</a> hay algo más sobre este tema.</p>
<h2 id="ojo-a-la-personalización-de-errores">Ojo a la personalización de errores</h2>
<p>Añado este apartado porque un mal uso en la creación de errores de salida puede causarnos mucho daño.</p>
<p>Lo habitual en Python es gestionar las excepciones mediantes sentencias <a href="https://docs.python.org/es/3/tutorial/errors.html#handling-exceptions">try…except</a>que nos devuelven los errores producidos. Pero <strong>debemos tener cuidado si añadimos mensajes personalizados</strong> porque pueden llevarnos a equívocos. Es mucho mejor recoger los errores que nos devuelve al sistema, tanto sin son los propios de Python (ValueError, RuntimeError, TypeError…) como los definidos para cada librería de terceros que usemos.</p>
<p>Último ejemplo. Dentro de complemento de QGIS, había definido una sentencia try/except en la que se ejecutaba un modelo de procesamiento de QGIS. Además de los mensajes de error que nos devuelve PyQGIS, se había añadido un aviso personalizado que indicaba que el modelo no había sido localizado. Este mensaje estaba pensado para saber que el perfil del usuario de QGIS que estaba ejecutando el programa no era el definido por defecto y que por lo tanto, no localizaba la carpeta donde se almacenaban los modelos del QGIS.</p>
<p>Aunque inicialmente el mensaje tenía su utilidad, la información que ofrecía centró la búsqueda del fallo en una dirección contraria a lo que de verdad estaba ocurriendo. El modelo fallaba porque al añadir un campo nuevo (status) en una capa que formaba parte del proceso de unión de varias capas, el tipo del nuevo campo no era el correcto (boolean) con el campo status de otra capa (tipo string), y por lo tanto el modelo se detenía.</p>
<p>Lo que se se soluciono simplemente añadiendo un paso más el flujo del modelo, tuvo un efecto mariposa que consumió mucho más tiempo buscando una posible solución en una línea incorrecta por un ‘bienintencionado’ pero incorrecto mensaje de error.</p>Patricio Soriano Castropasoriano@sigdeletras.comComo se suele decir “hasta de los errores se aprende”. Esta entrada me sirve para recopilar, organizar y exponer un conjunto de lecciones aprendidas durante el proceso de corrección de un error. Un error informático, en concreto de programación en un complemento de QGIS usando PyQGIS, la API para Python de este potente GIS.Creando un wrapper con Python de la API del Geocodificador SCN2022-06-19T00:00:00+00:002022-06-19T00:00:00+00:00https://sigdeletras.com/2022/creando-un-wrapper-con-python-de-la-api-del-gecodificador-scn<p>En la siguiente entrada voy a exponer un <strong>caso sencillo de acceso y consumo a datos geográficos a través de una API pública usando el lenguaje de programación Python</strong>.
<!--more--></p>
<p>Python dispone de librerías como <a href="https://docs.python.org/3/library/urllib.html">urlib</a> o <a href="https://pypi.org/project/requests/">requests</a> para realizar peticiones http a servicios Rest API. El siguiente código es un ejemplo de cómo podríamos obtener los datos de la API que vamos a usar dentro de un script.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">json</span>
<span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">request</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'https://geocoder-5-ign.larioja.org/v1/search?text=Sevilla'</span>
<span class="k">with</span> <span class="n">request</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="k">as</span> <span class="n">resp</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">loads</span><span class="p">(</span><span class="n">resp</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</code></pre></div></div>
<p>Intentando como siempre dar un paso más, en esta ocasión usaremos el paradigma de <strong>programación orientado a objetos (POO)</strong> y algunos aspectos básicos del desarrollo dirigido por test (TDD o <strong>Test-Driven Development</strong>) para crear un <strong>wrapper</strong> que permita abstraer el acceso a la API y personalizar tanto los datos obtenidos (atributos) como la forma de obtenerlos y manejarlos (métodos).</p>
<h2 id="la-api-servicio-de-geocodificación-de-direcciones-del-sistema-cartográfico-nacional">La API: Servicio de Geocodificación de direcciones del Sistema Cartográfico Nacional</h2>
<p>Gracias a unos <a href="https://mobile.twitter.com/gonzalo_lpgc/status/1501596985450766338">tuits</a> de Gonzalo López de IDERioja <a href="@https://twitter.com/gonzalo_lpgc">@gonzalo_lpgc</a> conocí el Servicio de Geocodificación de direcciones del Sistema Cartográfico Nacional (España). Según la <a href="https://cenormasgeograficas.github.io/geocodificador/">documentación</a>, esta Interfaz de Programación de Aplicaciones de geocodificación pública está diseñada para <em>“buscar y obtener a partir de sus datos identificativos, la localización geográfica de cualquier dirección que se encuentre ubicada dentro del territorio español”</em>.</p>
<p>Poder abrir este tipo de recursos geográficos y hacerlo en esta ocasión mediante un servicio de estas características permite la posibilidad de implementar de funciones de geocodificación dentro aplicaciones escritas en diferentes lenguajes. Muy muy interesante ¿verdad?</p>
<p>Como punto a su favor, hay también que decir que el servicio está basado en <a href="https://pelias.io/">Pelias</a>, un geocodificador modular de código abierto sobre Elasticsearch desarrollado por Mapzen.</p>
<p>Sin entrar en mucho detalle, los <em>endpoints</em> del Geocodificador de SCN permiten realizar:</p>
<ul>
<li>Geocodificación directa (/v1/search): Método que obtiene los datos y la ubicación de una dirección o lugar, a partir de sus datos identificativos o de referencia.</li>
<li>Geocodificación inversa (/v1/reverse): Método que busca las direcciones más próximas a un punto geográfico determinado.</li>
<li>Autocompletar (/v1/autocomplete): Método que obtiene resultados en tiempo real sin necesidad de completar todos los datos de identificación.</li>
<li>Geocodificación estructurada (/v1/search/structured): (beta) Método que encuentra un lugar a partir de datos estructurados en calle, número, ciudad, etc.</li>
<li>Lugar (/v1/place): Método que obtiene detalles sobre un lugar devuelto por una consulta anterior.</li>
</ul>
<p>En este primer acercamiento se va a implementar una clase que permite almacenar atributos y datos vinculados con la geocodificación directa e indirecta a partir de los parámetros básicos.</p>
<h2 id="test-driven-development">Test-Driven Development</h2>
<p>Aunque he realizado (pocos) algunos pinitos de testing en JavaScript, tenía mucho interés en comenzar a aprender cómo realizar desarrollos basados en pruebas.</p>
<p>Esta técnica de diseño e implementación de software implica escribir las pruebas primero (Test First Development) y posteriormente refactorizar (refactoring). Debemos partir de unos casos de usos, escribir la prueba, verificar que falla, realizar la implementación, lanzar las pruebas de nuevo y refactorizar.</p>
<p><img src="/images/blog/202206-wrapper/TDD_Global_Lifecycle.png" alt="Lifecycle of the Test-Driven Development method. Fuente: Wikipedia" />
<em>Lifecycle of the Test-Driven Development method. Fuente: Wikipedia</em></p>
<p>Python cuenta con la librería estándar <a href="https://docs.python.org/3/library/unittest.html">unittest</a> para pruebas unitarias. A pesar de ello, las consultas previas sobre este tema apuntaban al uso del paquete de terceros <a href="https://docs.pytest.org/en/7.1.x/">pytest</a>. Este marco de pruebas no necesitar crear clases como en unittest y el manejo aserciones (asserts) parece ser más sencillo.</p>
<p>La mejor forma de usar librerías externas en crear un entorno virtual en Python e instalarlas. Llevo algún tiempo usado PyCharm y la gestión de entornos virtuales es bastante sencilla en este sentido</p>
<h2 id="creación-de-la-clase-geocoderscn">Creación de la clase GeocoderSCN</h2>
<p>El <em>wrapper</em> o adaptador de la REST API estará compuesto por una clase que he llamado GeocoderSCN. En sus atributos no solo se va a almacenar el GeoJSON de la API, es decir aquellos elementos puntuales que coincidan con la dirección indicada. Quiero también tener disponible la URL de la petición, el texto de búsqueda, el código de la petición HTTP, el total de coincidencias obtenidas y un registro de posibles errores.</p>
<p>Lo primero que vamos a hacer es crear el archivo que almacenará la clase. En vez de usar el método reservado <strong>init</strong> como constructor de la clase definiremos los atributos con el módulo <a href="https://docs.python.org/3/library/dataclasses.html">dataclasses</a> y el decorador <em>dataclass</em>.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
<span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">GeocoderSCN</span><span class="p">:</span>
<span class="s">"""Class for saving the information from the SCN geocoder"""</span>
<span class="n">searchtext</span><span class="p">:</span> <span class="nb">str</span>
</code></pre></div></div>
<h2 id="escribiendo-los-test">Escribiendo los test</h2>
<p>Nuestro primer test está destinado a crear los atributos de la clase. Los script pruebas deben teber el prefijo ‘test_’ o bien ser almacenados en un carpeta denominada ‘test’</p>
<p>Para lanzarlos se usa el comando pytest o se ejecuta desde el framework.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># test/test_geocoderscn.py
</span>
<span class="k">def</span> <span class="nf">test_attributes</span><span class="p">():</span>
<span class="n">my_geocoderSCN</span> <span class="o">=</span> <span class="n">GeocoderSCN</span><span class="p">(</span><span class="s">'Plaza de las Tendillas 1 Córdoba'</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">search_text</span> <span class="o">!=</span> <span class="s">''</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">endpoint</span> <span class="ow">is</span> <span class="bp">None</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">feature_count</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">api_data</span> <span class="ow">is</span> <span class="bp">None</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">status</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">error</span> <span class="ow">is</span> <span class="bp">False</span>
<span class="k">assert</span> <span class="n">my_geocoderSCN</span><span class="p">.</span><span class="n">messages</span> <span class="ow">is</span> <span class="bp">None</span>
</code></pre></div></div>
<p>Al ejecutarlo vemos que el test falla.</p>
<p><img src="/images/blog/202206-wrapper/01_test_fail.PNG" alt="Test sin pasar" /></p>
<p>Es el momento de añadir los atributos a nuestra clase.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">GeocoderSCN</span><span class="p">:</span>
<span class="s">"""Class for saving the information from the SCN geocoder"""</span>
<span class="n">searchtext</span><span class="p">:</span> <span class="nb">str</span>
<span class="n">endpoint</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">feature_count</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">api_data</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">status</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">error</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="bp">False</span>
<span class="n">messages</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="bp">None</span>
</code></pre></div></div>
<p>Lanzamos de nuevo los test y vemos que han pasado.</p>
<p><img src="/images/blog/202206-wrapper/02_test_passed.PNG" alt="Test pasados" /></p>
<h2 id="función-de-geolocalización-directa">Función de geolocalización directa.</h2>
<p>La documentación de la API nos indica que las búsquedas de geocodificación directa. Vemos un ejemplo.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://geocoder-5-ign.larioja.org/v1/search?text=Plaza de las Tendillas 1 Córdoba
</code></pre></div></div>
<p><img src="/images/blog/202206-wrapper/03_json.PNG" alt="resultados de geocidifiación directa" /></p>
<p>Existe también una aplicación gráfica para testear los servicios basados en Pelias que ofrece una interfaz más amigable además de la representación de los resultados en un mapa.</p>
<p><a href="https://pelias.github.io/compare/">https://pelias.github.io/compare/</a></p>
<p><img src="/images/blog/202206-wrapper/04_pelias.PNG" alt="Programa de pruebas de servicios basados en Pelias" /></p>
<p>La API de devuelve un GeoJSON donde encontramos una información general de la búsqueda (geocoding) y a continuación los datos y coordenadas de cada uno de los resultados. La petición estará implementada dentro de la clase en un método denominada search. Como librerías necesarias se usará urllib y json. El método evaluará los resultados y almacenará no solo el GeoJSON de respuesta sino los datos de interés (endpoint, total de resultados y posibles errores).</p>
<p>Como parámetros del método <em>search()</em> se pasará por defecto:</p>
<ul>
<li>La URL de la API (api=API) pasando una variable global con la dirección actual del servicio.</li>
<li>El parámetro <em>layers=’address’</em> que corresponde con datos sobre puntos con una dirección postal. Existe también las opciones de calles, vías y carreteras (street) o topónimos, puntos de interés y nombres propios de las direcciones (venue)</li>
<li>El parámetro <em>size</em> con el número deseado de resultados que por defecto son 10.</li>
</ul>
<p>Implementamos un primer test con las aserciones esperadas. En esta ocasión dentro de los test usaremos las <em>fixtures</em> de pytest que preinicializan datos, son reaprovechables y disminuyen las líneas de código.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">pytest</span><span class="p">.</span><span class="n">fixture</span>
<span class="k">def</span> <span class="nf">my_GeocoderSCN</span><span class="p">():</span>
<span class="n">my_geocoderSCN</span> <span class="o">=</span> <span class="n">GeocoderSCN</span><span class="p">(</span><span class="s">'Acera Fuente de los Picadores 2 Córdoba'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">my_geocoderSCN</span>
<span class="o">@</span><span class="n">pytest</span><span class="p">.</span><span class="n">fixture</span>
<span class="k">def</span> <span class="nf">my_GeocoderSCN_search</span><span class="p">(</span><span class="n">my_GeocoderSCN</span><span class="p">):</span>
<span class="n">my_GeocoderSCN</span><span class="p">.</span><span class="n">search</span><span class="p">()</span>
<span class="k">return</span> <span class="n">my_GeocoderSCN</span>
<span class="p">....</span>
<span class="k">def</span> <span class="nf">test_search</span><span class="p">(</span><span class="n">my_GeocoderSCN_search</span><span class="p">):</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">search_text</span> <span class="o">!=</span> <span class="s">''</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">endpoint</span> <span class="o">!=</span> <span class="s">''</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">api_data</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">feature_count</span> <span class="o">></span> <span class="mi">0</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">status</span> <span class="o">==</span> <span class="mi">200</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">error</span> <span class="ow">is</span> <span class="bp">False</span>
<span class="k">assert</span> <span class="n">my_GeocoderSCN_search</span><span class="p">.</span><span class="n">messages</span> <span class="o">==</span> <span class="s">"it's all OK!"</span>
</code></pre></div></div>
<p>El código del método test válido es el siguiente:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">api</span><span class="o">=</span><span class="n">API</span><span class="p">,</span> <span class="n">layers</span><span class="o">=</span><span class="s">'address'</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span>
<span class="n">text_parse</span> <span class="o">=</span> <span class="n">parse</span><span class="p">.</span><span class="n">quote_plus</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">search_text</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">endpoint</span> <span class="o">=</span> <span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">API</span><span class="si">}</span><span class="s">/search?text=</span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">search_text</span><span class="si">}</span><span class="s">&layers=</span><span class="si">{</span><span class="n">layers</span><span class="si">}</span><span class="s">&size=</span><span class="si">{</span><span class="n">size</span><span class="si">}</span><span class="s">'</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">api</span><span class="si">}</span><span class="s">/search?text=</span><span class="si">{</span><span class="n">text_parse</span><span class="si">}</span><span class="s">&layers=</span><span class="si">{</span><span class="n">layers</span><span class="si">}</span><span class="s">&size=</span><span class="si">{</span><span class="n">size</span><span class="si">}</span><span class="s">'</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="n">request</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="k">as</span> <span class="n">resp</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">resp</span><span class="p">.</span><span class="n">status</span>
<span class="bp">self</span><span class="p">.</span><span class="n">api_data</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">loads</span><span class="p">(</span><span class="n">resp</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="bp">self</span><span class="p">.</span><span class="n">feature_count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">api_data</span><span class="p">[</span><span class="s">'features'</span><span class="p">])</span>
<span class="bp">self</span><span class="p">.</span><span class="n">messages</span> <span class="o">=</span> <span class="s">"it's all OK!"</span>
<span class="k">except</span> <span class="n">HTTPError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">error</span> <span class="o">=</span> <span class="bp">True</span>
<span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">code</span>
<span class="bp">self</span><span class="p">.</span><span class="n">messages</span> <span class="o">=</span> <span class="n">e</span>
<span class="k">except</span> <span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">error</span> <span class="o">=</span> <span class="bp">True</span>
<span class="bp">self</span><span class="p">.</span><span class="n">messages</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">reason</span>
</code></pre></div></div>
<p>Nuestra clase incorpora dos métodos más:</p>
<ul>
<li>reverse() para realizar la geocodificación inversa</li>
<li>get_list() Un sencillo método para obtener una lista de diccionarios con los datos básicos (longitud, latitud, etiqueta y fuente)</li>
</ul>
<p>Todo el código está disponible en <a href="https://github.com/sigdeletras/geocodificador-scn-wrapper">GitHub</a></p>
<h2 id="y-todo-esto-para-qué">Y todo esto ¿para qué?</h2>
<p>Personalmente tenía ganas de indagar en las posibilidades de la programación orientada a objetos desde Python. Contar con un objeto en el que almacenar los atributos que modelemos y definir tus propios métodos creo que tiene mucha utilidad.</p>
<p>Cuando conocí esta REST API lo primero que me vino a la cabeza fue montar un pluging de QGIS. La cuestión está en que ya existe un complemento llamado <a href="https://plugins.qgis.org/plugins/PeliasGeocoding/">Pelias Geocoding</a> con todas las funcionalidades incorpoadas al que solo hace falta añadir la url proveedor.</p>
<p><img src="/images/blog/202206-wrapper/05_pluging_qgis.PNG" alt="Pluging Pelias Geocoder" /></p>
<p>Este descubrimiento fue algo posterior. A pesar de ello y sún las experiencas anteriores de desarrollo complementos con acceso a datos públicos ya habían aparecedo algunas preguntas en mi cabeza:</p>
<ul>
<li>¿Y sí cambia la dirección de la API?</li>
<li>¿Cómo gestiono los posibles errores de conexión o falta de parámetros?</li>
<li>¿Y si necesito sacar solo unos datos fuera del GeoJSON?</li>
<li>¿Podría reutilizar el código fuera del pluging de QGIS, por ejemplo con Jupiter Lab?</li>
</ul>
<p>Todas estas preguntas me llevaron a poner en marcha este pequeño ‘side-project’ para abstraer el de acceso a la API mediante un clase y añadir test del desarrollo. La librería código puede puede incluso convertirse en una librería pública y ser instalada y usada por cualquier usuario. Ya hay una similar denominada <a href="https://pypi.org/project/pyPelias/">pyPelias</a> para cualquier servicio que use Pelias. He probado a usarla la que yo he creado con Jupyter Lab y pienso que puede dar mucho juego.</p>
<p><img src="/images/blog/202206-wrapper/jupyter.PNG" alt="" /></p>
<p>Otro gran tema está en los tests. Ahora mismo programar pensando en los tests ha sido más lento pero esto se debe más a mi desconocimiento inicial del Test-Driven Development. Los beneficios obtenidos superan con creces esta lentitud inicial. Me ha hecho ser más preciso al definir los caso de uso, he aprovechado más el código testeado y aunque siempre puede haber fallos, mi sensación es que el código es más robusto y limpio.</p>Patricio Soriano Castropasoriano@sigdeletras.comEn la siguiente entrada voy a exponer un caso sencillo de acceso y consumo a datos geográficos a través de una API pública usando el lenguaje de programación Python.Comunicación con el usuario y logging para plugins de QGIS2021-09-18T00:00:00+00:002021-09-18T00:00:00+00:00https://sigdeletras.com/2021/comunicacion-con-el-usuario-y-logging-para-plugins-de-qgis<p>Escuché hace un tiempo una noticia de cómo la comunicación fluida con los pasajeros en los aeropuertos (hora del vuelo, tiempo restante, retrasos…) mejoraba considerablemente la experiencia de estos. Tener información de lo que está pasando o va a pasar es de gran ayuda y reduce el nerviosismo, la ansiedad o la incertidumbre que puede suponer hacer un vuelo, sobre todo si no se hace con frecuencia.
<!--more--></p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/d/d0/MUCFIDS.jpg" alt="" /></p>
<p>Cuando programamos una aplicación o página web esta <strong>experiencia de usuario</strong> se mejora siguiendo las especificaciones funcionales marcadas en el diseño previo del aplicativo.</p>
<p>Puede ocurrir que el desarrollo sea técnicamente correcto, que estén definidas tanto las entradas y salidas que va a producir y que si alguno de los procesos falla existan un flujo para su correcta solución.</p>
<p>Cuando estamos programando la aplicación, tenemos muchas herramientas para comprobar que todo vaya de la forma deseada. Pero cuando el trabajo ya está en producción y está siendo usado por el usuario final, <strong>el caos, las llamadas y las quejas comienzan a producirse cuando el cliente no recibe la información de posibles motivos que hacen que el programa “haga lo que debe de hacer”</strong>. Todo esto conlleva una percepción negativa del producto con las consecuencias que esto puede traer.</p>
<p>En la siguiente entrada se va a exponer diversas <strong>herramientas que la API de QGIS podemos usar para mejorar esa comunicación con el usuario final cuando desarrollamos un complemento de QGIS</strong>.</p>
<p>Al programar usando PyQGIS contamos ya con un conjunto de opciones que nos van a facilitar añadir estas ayudas. Veremos estas posibilidades y las completaremos usando el módulo logging de Python orientado al registro procesos.</p>
<h2 id="requisitos-funcionales-de-nuestro-complemento-de-qgis">Requisitos funcionales de nuestro complemento de QGIS.</h2>
<p>He usado el repositorio <a href="https://github.com/wonder-sk/qgis-minimal-plugin">QGIS Minimal Plugin</a> de Martin Dobias que contiene los archivos y configuración mínimos para hacer un complemento de QGIS.</p>
<p>El complemento añade un botón denominado “Check!” a la barra de QGIS que realiza los siguientes procesos.</p>
<ul>
<li>(P01) Localiza la capa llamada <em>points</em> en nuestro proyecto de QGIS.</li>
<li>(P02) Realizar una conexión a una base de datos PostGIS.</li>
<li>(P03) Devuelve información de OSM en formato JSON desde API REST de Nominatim a partir de unas coordenadas.</li>
</ul>
<p>Este flujo podría corresponderse con un proyecto real que realiza un análisis de una capa del proyecto evaluando si hay cambios o discrepancias. Si existen, podríamos necesitar actualizar esas modificaciones en nuestra base de datos. Y para finalizar, queremos que todo el proceso de revisión quede almacenado en una aplicación corporativa a la accedemos mediante una API Rest previa autenticación.</p>
<p>Tras realizar estas comprobaciones, se presenta un mensaje indicado que las tres operaciones se han realizado correctamente.</p>
<p><img src="/images/blog/202109-logging/00_plugin.jpg" alt="Resultado final" /></p>
<p>Si alguno de los tres análisis no se realizar la ejecución finaliza. Esto se ha programado usando <a href="https://docs.python.org/3/tutorial/errors.html">excepciones try/except</a>. Pero <strong>el problema está que en el diseño original no se ofrece al usuario ningún mensaje sobre los motivos por lo que el complemento ha fallado</strong> (no encontramos la capa, la conexión a la base de datos no se ha realizado, no obtenemos los datos de la API…) por lo que la experiencia de usuario empieza a hacer aguas.</p>
<h2 id="información-a-nivel-usuario">Información a nivel usuario</h2>
<p>Nos basaremos en el diagrama de flujo que muestra los requisitos funcionales del desarrollo.</p>
<p><img src="/images/blog/202109-logging/flow_chart.png" alt="Flow chart" /></p>
<p>Vamos a usar los dos primeros procesos (P01 y P02) para ver las opciones que tenemos para comunicarnos con el usuario dentro de QGIS.</p>
<h3 id="función-print">Función print()</h3>
<p>Si no encontramos la capa points en nuestro proyecto vamos generar un aviso usando la función print() de Python.</p>
<p>El mensaje de salida usará literales de cadenas formateadas (<a href="https://docs.python.org/3/reference/lexical_analysis.html#f-strings">f-string</a>) para añadir el nombre de la capa. Esto nos permitiría pasar a una función el código y reaprovecharlo.</p>
<p>Completamos los mensajes devolviendo también el error de la excepción.</p>
<p>Todas las excepciones contarán con una instrucción <em>return</em> que forzará final de la función paralizando por tanto las demás revisiones.</p>
<pre><code class="language-Python">
def check():
"""Función que realiza una serie de comprobaciones y muestra el resultado en un mensaje
"""
check_message = 'RESULTADO:\n\n'
# P01 Busca una capa y devuelve su nombre
LAYER = 'points'
try:
print('Check 01 Start')
points_layer = QgsProject.instance().mapLayersByName(LAYER)[0]
check_message += f'01 - La capa \'{points_layer.name()}\' se encuentra cargada.\n'
print('Check 01 - OK')
except Exception as error:
error_message = f'Check 01 - FAIL - La capa {LAYER} no se encuentra en el proyecto'
# 1 - Usamos print
print(error_message)
print(f'Error: {error}')
return
</code></pre>
<p>Para realizar un test de nuestro código, vamos a cambiar el nombre de la capa a “points_2”, abriremos la Consola de Python de QGIS y ejecutamos nuestro complemento.</p>
<p><img src="/images/blog/202109-logging/01_pyhton.jpg" alt="IMG" /></p>
<h3 id="qgsmessagelog">QgsMessageLog</h3>
<p>Con la clase <a href="https://qgis.org/pyqgis/3.2/core/Message/QgsMessageLog.html">QgsMessaLog</a> de PyQGIS seremos capaces de mostrar información en el Panel de Mensajes de Registro de QGIS.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
<span class="n">error_message</span> <span class="o">=</span> <span class="sa">f</span><span class="s">'Check 01 - FAIL - La capa </span><span class="si">{</span><span class="n">LAYER</span><span class="si">}</span><span class="s"> no se encuentra en el proyecto'</span>
<span class="c1"># 1 - Usamos print
</span> <span class="k">print</span><span class="p">(</span><span class="n">error_message</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'Error: </span><span class="si">{</span><span class="n">error</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="c1"># 2 - QgsMessageLog
</span> <span class="n">QgsMessageLog</span><span class="p">.</span><span class="n">logMessage</span><span class="p">(</span><span class="n">error_message</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">Qgis</span><span class="p">.</span><span class="n">Critical</span><span class="p">)</span>
<span class="n">QgsMessageLog</span><span class="p">.</span><span class="n">logMessage</span><span class="p">(</span>
<span class="sa">f</span><span class="s">'Error: </span><span class="si">{</span><span class="n">error</span><span class="si">}</span><span class="s">'</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">Qgis</span><span class="p">.</span><span class="n">Critical</span><span class="p">)</span>
<span class="k">return</span>
<span class="p">...</span>
</code></pre></div></div>
<p><img src="/images/blog/202109-logging/02_panel.jpg" alt="IMG" /></p>
<h3 id="qgsmessagebar">QgsMessageBar</h3>
<p>Las opciones anteriores <strong>requieren que el usuario tenga abierta bien la consola de Python o el Panel de Mensajes de Registro</strong>.</p>
<p>A no ser que se tenga cierto nivel de conocimiento de QGIS, estas dos funcionalidades nos van a pasar desapercibidas. Pueden ser de gran ayuda si estamos desarrollando nosotros mismos, pero si es un proyecto para un cliente no es la mejor opción.</p>
<p>La clase <a href="https://qgis.org/pyqgis/3.0/gui/Message/QgsMessageBar.html">QgsMessageBar</a> nos ayudará en este sentido.</p>
<p>La vamos a implementar en el segundo proceso (P02) donde realizamos una conexión a una base de datos usando la librería Python <a href="https://www.psycopg.org/docs/">psycopg2</a></p>
<p>Forzamos el error introduciendo mal el nombre de la base de datos y vemos el resultado.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="p">...</span>
<span class="c1"># P02 Realiza una conexión a una DB
</span> <span class="n">conn</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">conn</span> <span class="o">=</span> <span class="n">psycopg2</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">'localhost'</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">5432</span><span class="p">,</span> <span class="n">database</span><span class="o">=</span><span class="s">'errordb'</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="s">'postgres'</span><span class="p">,</span> <span class="n">password</span><span class="o">=</span><span class="s">'postgres'</span><span class="p">)</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="n">cur</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">check_message</span> <span class="o">+=</span> <span class="sa">f</span><span class="s">'02 - Conexión correcta a la db</span><span class="se">\n</span><span class="s">'</span>
<span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
<span class="n">error_message</span> <span class="o">=</span> <span class="s">'Check 02 - FAIL No se ha podido establecer la conexión a la DB'</span>
<span class="c1"># 3 - messageBar()
</span> <span class="n">iface</span><span class="p">.</span><span class="n">messageBar</span><span class="p">().</span><span class="n">pushMessage</span><span class="p">(</span><span class="s">"ERROR"</span><span class="p">,</span> <span class="n">error_message</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">Qgis</span><span class="p">.</span><span class="n">Critical</span><span class="p">)</span>
<span class="k">return</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">conn</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">conn</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="p">...</span>
</code></pre></div></div>
<p><img src="/images/blog/202109-logging/03_QgsMessageBar.jpg" alt="IMG" /></p>
<h2 id="logging-a-nivel-desarrollo">Logging a nivel desarrollo</h2>
<p>Todo lo mostrado hasta ahora fortalece la comunicación con el usuario de SIG. Pero como he comentado anteriormente, <strong>el registro de procesos y errores no es accesible para el desarrollador ya que es únicamente accesible en una sesión de trabajo</strong>. Cuando se cierre QGIS, todos esos datos se perderán.</p>
<p>Para poder generar un archivo con esta información, o lo que comúnmente se denomina un log de registro, usaremos otra librería estándar de Python denominada <a href="https://docs.python.org/3/library/logging.html">logging</a>.</p>
<p>Con logging podremos programar el lanzamiento de mensajes de aviso con distintos niveles de severidad. Estos mensajes pueden ofrecerse por consola, almacenados en uno fichero o varios ficheros que puede ser guardados en local o remoto, formatear el texto de registro o integrarlo en varios módulos de nuestra librería. La documentación de la librería contiene cantidad de <a href="https://docs.python.org/es/3/howto/logging.html">ejemplos</a>.</p>
<p>En nuestro plugin configuramos el código para que cree un fichero de tipo .log en una carpeta concreta dentro del complemento de QGIS. En este fichero se irá registrando lo que ocurre en nuestra aplicación según un formato definido.</p>
<p>Nuestra tercera comprobación va a corresponder con un acceso y petición HTTP a la API abierta de geocodificación <a href="https://nominatim.org/release-docs/develop/api/Overview/">Nominatim</a> basada en OpenStreetMap.</p>
<p>La petición GET será realizada con la librería <a href="https://docs.python.org/es/3/howto/urllib2.html">urllib</a>. Si pasamos por ejemplo una url inválida, no pasamos los parámetros correctos o no es posible realizar la conexión la excepción devolverá el mensaje de error y saldrá del flujo.</p>
<p>La librería urllib cuenta con su propia clase <a href="https://docs.python.org/3/library/urllib.error.html">urllib.error</a> para la gestión de errores que usaremos.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c1"># P03 Consulta una API
</span> <span class="n">URL_NOMINATIM</span> <span class="o">=</span> <span class="s">'https://nominatim.openstreetmap.org/reverse?'</span>
<span class="n">COORDINATES</span> <span class="o">=</span> <span class="p">[</span><span class="mf">37.87893</span><span class="p">,</span> <span class="o">-</span><span class="mf">4.772846</span><span class="p">]</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">URL_NOMINATIM</span><span class="si">}</span><span class="s">format=jsonv2&lat=</span><span class="si">{</span><span class="n">COORDINATES</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s">&lon=</span><span class="si">{</span><span class="n">COORDINATES</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s">'</span>
<span class="n">url_2</span> <span class="o">=</span> <span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">URL_NOMINATIM</span><span class="si">}</span><span class="s">format=jsonv2&lat=</span><span class="si">{</span><span class="n">COORDINATES</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s">&lon='</span>
<span class="k">with</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">msg</span> <span class="o">+=</span> <span class="sa">f</span><span class="s">'03 - Consulta a la API relizada</span><span class="se">\n</span><span class="s">'</span>
<span class="k">except</span> <span class="n">urllib</span><span class="p">.</span><span class="n">error</span><span class="p">.</span><span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">return</span>
</code></pre></div></div>
<p>Creamos una nueva función que hemos llamado <em>create_loging_file()</em> destinada a configurar y crear el log.</p>
<p>La función tendrá la responsabilidad de indicar el nombre y la ubicación del archivo, así como de su formato. Estos parámetros serán usados para crear una configuración básica del logger.</p>
<p>Una vez lanzada la función y ya dentro de la función principal <em>check()</em>, se ha definido la creación de fichero para que se vayan añadiendo las líneas de registro.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">create_loging_file</span><span class="p">():</span>
<span class="s">"""Crear y configura un fichero logger de registro
"""</span>
<span class="n">log_path_save</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">__file__</span><span class="p">).</span><span class="n">parent</span><span class="p">.</span><span class="n">absolute</span><span class="p">()</span>
<span class="n">log_filename</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">log_path_save</span><span class="p">)</span><span class="o">+</span><span class="s">"/log/logfile.log"</span>
<span class="n">log_format</span> <span class="o">=</span> <span class="s">'%(asctime)s - %(name)s - %(levelname)s - %(message)s'</span>
<span class="n">logging</span><span class="p">.</span><span class="n">basicConfig</span><span class="p">(</span>
<span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="p">.</span><span class="n">DEBUG</span><span class="p">,</span> <span class="c1"># Nivel de los eventos que se registran en el logger
</span> <span class="n">filename</span><span class="o">=</span><span class="n">log_filename</span><span class="p">,</span> <span class="c1"># Fichero de logs
</span> <span class="nb">format</span><span class="o">=</span><span class="n">log_format</span> <span class="c1"># Formato de registro
</span> <span class="p">)</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">log_filename</span><span class="p">):</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">log_filename</span><span class="p">,</span> <span class="s">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="nb">file</span><span class="p">:</span>
<span class="k">pass</span>
<span class="n">logging</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"############### START LOGGING ###############"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">check</span><span class="p">():</span>
<span class="s">"""Función que realiza una serie de comprobaciones y muestra el resultado en un mensaje
"""</span>
<span class="n">create_loging_file</span><span class="p">()</span>
<span class="p">...</span>
</code></pre></div></div>
<p>Nos queda ya solo ir añadiendo los logs según los niveles que definamos. Sin duda dentro de las excepciones será de tipo ERROR.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="k">except</span> <span class="n">urllib</span><span class="p">.</span><span class="n">error</span><span class="p">.</span><span class="n">URLError</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
<span class="n">error_message</span> <span class="o">=</span> <span class="s">'Check 03 - FAIL Consulta a la API no relizada'</span>
<span class="c1"># 4 - logging
</span> <span class="n">logging</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="s">'Check 03 - FAIL'</span><span class="p">)</span>
<span class="n">logging</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">error</span><span class="p">.</span><span class="n">reason</span><span class="p">)</span>
<span class="k">return</span>
<span class="p">...</span>
</code></pre></div></div>
<p>Si abrimos nuestro archivo de registro veremos que se han ido almacenando los mensajes configurados y que se han realizado dos llamadas en las que la URL de la API no estaba correcta y otra en la que la petición no estaba bien definida por obviar uno los parámetros.</p>
<p><img src="/images/blog/202109-logging/04_logging_api_error.jpg" alt="API error" /></p>
<h2 id="versión-final-y-conclusiones">Versión final y conclusiones</h2>
<p>El complemento terminaría definiendo los mensajes de registro de nivel INFO que también quisiéramos añadir en el archivo log. La versión final se encuentra en este <a href="https://github.com/sigdeletras/minimal_check">repositorio de GitHub</a></p>
<p>Podríamos eliminar todas las salidas de la función print() ya que el usuario no las va a consultar.</p>
<p>Las opciones de logging son muy amplias y podemos llegar a tener varios archivos log, definir un módulo concreto que pueda ser usado para todo el código del complemento o añadir un archivo de configuración tipo .ini o en formato yaml… pero todo ya queda fuera del objetivo de esta entrada.</p>
<p>Como conclusión, solo quiero recalcar que contamos con las herramientas suficientes para ofrecer información a los usuarios de nuestros desarrollos esto nos va a reducir los quebraderos de cabeza.</p>
<p>Es también necesario tener en cuenta los datos que podamos ofrecer a nivel de diseño de la aplicación tanto si somos los desarrolladores del código como si debemos marcar los requisitos por ser el responsable del proyecto.</p>
<h2 id="recursos">Recursos</h2>
<ul>
<li><a href="https://qgis.org/pyqgis/3.0/gui/Message/QgsMessageBar.html">QgsMessageBar class</a></li>
<li><a href="https://qgis.org/pyqgis/3.2/core/Message/QgsMessageLog.html">QgsMessaLog class</a></li>
<li><a href="https://docs.python.org/3/tutorial/errors.html">try/except with Python</a></li>
<li><a href="https://docs.python.org/3/reference/lexical_analysis.html#f-strings">f-string</a></li>
<li><a href="https://www.psycopg.org/docs/">psycopg2 library</a></li>
<li><a href="https://docs.python.org/es/3/howto/urllib2.html">urllib2 how to</a></li>
<li><a href="https://docs.python.org/es/3/howto/logging.html">logging how to</a></li>
<li><a href="https://docs.python.org/es/3/library/logging.html">logging library</a></li>
<li><a href="https://www.datadoghq.com/blog/python-logging-best-practices/">How to collect, customize, and centralize Python logs</a></li>
<li><a href="https://realpython.com/python-logging/">Logging in Python</a></li>
</ul>Patricio Soriano Castropasoriano@sigdeletras.comEscuché hace un tiempo una noticia de cómo la comunicación fluida con los pasajeros en los aeropuertos (hora del vuelo, tiempo restante, retrasos…) mejoraba considerablemente la experiencia de estos. Tener información de lo que está pasando o va a pasar es de gran ayuda y reduce el nerviosismo, la ansiedad o la incertidumbre que puede suponer hacer un vuelo, sobre todo si no se hace con frecuencia.#GEOApuntes 3: docker geoserver, aprendizaje-servicio, espacios verdes públicos y edificios de Andalucía2021-09-06T00:00:00+00:002021-09-06T00:00:00+00:00https://sigdeletras.com/2021/geoapuntes3<h2 id="recursos-imagen-de-geoserver-de-geomatico">RECURSOS: Imagen de GeoServer de Geomatico</h2>
<ul>
<li>Enlace: <a href="https://geomatico.es/en/100k-pulls-of-our-docker-geoserver/">https://geomatico.es/en/100k-pulls-of-our-docker-geoserver/</a></li>
<li>Fuente: Linkedin</li>
</ul>
<p>Contad en una empresa tecnológica con una persona que maneje de forma avanzada Docker es sin duda un valor añadido. Llevo aproximadamente tres trabajando con imágenes y contenedores Docker pero a nivel de usuario.</p>
<p>Pero saber montar una imagen o crear correctamente un contenedor que tiren de varias imágenes, que esté correctamente parametrizado, gestiona correctamente volúmenes de datos y ya que decir que pueda ser desplegado en producción es harina de otro costal.</p>
<p>Para los que nos movemos a nivel básico es preferible aprovecharse de los que realmente saben hacer las cosas. Esta es la razón por es interesante aprovechar la <a href="https://hub.docker.com/r/oscarfonts/geoserver">imagen de GeoServer gestionada por la Óscar Fonts de Geomatico.com</a> merece la pena ser guardada en este GEOApuntes.</p>
<p>Sumo a favoritos el <a href="https://github.com/GeographicaGS/Docker-PostGIS">repositorio de imágenes de Postgres/PostGIS en GitHub de la gente de (la antigua) Geographica</a> por si alguien está interesado.</p>
<h2 id="programación-aprendizaje-servicio-en-el-desarrollo-de-software">PROGRAMACIÓN: Aprendizaje-Servicio en el desarrollo de software</h2>
<ul>
<li>Enlace: <a href="https://us2.campaign-archive.com/?u=374c664073e1a1fa3deca53b4&id=5f38e5523a">https://us2.campaign-archive.com/?u=374c664073e1a1fa3deca53b4&id=5f38e5523a</a></li>
<li>Fuente: Lista de correos</li>
</ul>
<p>Los domingos llega a mi correo <a href="bonilista.com">La Bonilista</a> de <a href="https://twitter.com/david_bonilla">David Bonilla</a>. Me gusta sacar un rato para leer los artículos sobre el sector y la industria tecnológica. Los textos me son bastante atractivos tanto por la temático como por el estilo con el que son escritos.</p>
<p>El pasado 29 de agosto, guarde en la lista de Notion el artículo de Raúl Recacha titulado <a href="https://us2.campaign-archive.com/?u=374c664073e1a1fa3deca53b4&id=5f38e5523a">“Aprendizaje-Servicio en el desarrollo de software”</a> en que se explica qué son los proyectos aprendizaje-servicio en relación con aquellos proyectos o iniciativas enfocadas en aprender una nueva habilidad tecnológica (lenguaje, framework…) pero haciendo un servicio a la comunidad.</p>
<p>Esto me ha hecho pensar la gran cantidad de tiempo que he dedico a aprender o mejorar mi capacidad de alguna herramienta tecnológica vinculada con la información geográfica. Quizás parte de estas horas podrían ser de más utilidad eligiendo una temática de interés general, con un beneficio social o de utilidad para alguna comunidad o asociación.</p>
<p>Echo de menor las actividades de voluntariado que organizábamos en <a href="https://wiki.osgeo.org/wiki/Category:Geoinquietos_C%C3%B3rdoba">Geoinquietos Córdoba</a> como los proyectos para HOT, el mapeado se infraestructuras de bicicetas, ediciones para mejorar OpenStreetMap y la utilidad que estas podrían tener al menos a nivel local.</p>
<h2 id="casos-de-uso-sig-para-la-evaluación-y-valoración-de-los-espacios-verdes-públicos-municipales">CASOS DE USO: SIG para la evaluación y valoración de los espacios verdes públicos municipales.</h2>
<ul>
<li>Enlace: <a href="https://www.europapress.es/cantabria/noticia-torrelavega-tiene-superficie-verde-relativamente-importante-distribucion-espacios-desequilibrada-20210412130511.html">https://www.europapress.es/cantabria/noticia-torrelavega-tiene-superficie-verde-relativamente-importante-distribucion-espacios-desequilibrada-20210412130511.html</a></li>
<li>Fuente: Prensa</li>
</ul>
<p>He dejado marcado este Trabajo de Fin de grado realizado por <strong>Darío Puente</strong> en el que evalúa y valora los espacios verdes municipales de Torrelavega y que según vi en la noticia (pasada) va a ser usado por el Ayuntamiento para equilibrar la distribución de suelo público dedicado a espacios verdes.</p>
<p>Por mi relación profesional pasada con la gestión municipal a nivel técnico, siempre estoy atento a ejemplos de aplicación de los SIG a aspecto relativos al análisis y diagnóstico de lo urbano. Según leo se han analizado aspectos relativos a la <strong>fragmentación y discontinuidad en la ubicación de las áreas verdes, o la ratio de espacios verdes por habitante</strong>.</p>
<p>El TFG está disponible en el <a href="https://us2.campaign-archive.com/?u=374c664073e1a1fa3deca53b4&id=5f38e5523a">repositorio de la Universidad de Cantabria</a></p>
<h2 id="recursos-caracterización-y-distribución-del-espacio-construido-en-andalucía">RECURSOS: Caracterización y distribución del espacio construido en Andalucía.</h2>
<ul>
<li>Enlace: Varios</li>
<li>Fuente: Lista de correos</li>
</ul>
<p>El Instituto de Estadística y Cartografía de Andalucía está generando una serie de <strong>mallas estadísticas de 250m x 250m</strong> para su descarga (shape) o acceso mediante WMS/WFS relativas distintos <strong>aspectos vinculados con la caracterización y distribución del parque de edificios construidos</strong> en Andalucía a partir de Catastro Inmobiliario.</p>
<p>Por ahora pueden consultarse:</p>
<ul>
<li><a href="https://www.juntadeandalucia.es/institutodeestadisticaycartografia/tipologiasconstructivas/index.htm">Distribución Espacial de las Tipologías Constructivas Catastrales</a></li>
<li><a href="https://www.juntadeandalucia.es/institutodeestadisticaycartografia/espacios-construidos/edificios/index.htm">Edificios (mediana del año de antigüedad, total de edificios nº de plantas, usos principales)</a></li>
<li><a href="https://www.juntadeandalucia.es/institutodeestadisticaycartografia/espacios-construidos/viviendas/index.htm">Viviendas (mediana del año de antigüedad, nº de viviendas, superficie, colectivas, unifamiliares, edificación rural)</a>.</li>
</ul>
<p>Tener todos estos datos al alcance de un clic, teniendo siempre claro el nivel de desagraguegación de los datos está realemente bien. Para todo lo demás…Catastro.</p>
<p>Mercator mediante, la semana que viene más…🌍</p>
<p><a href="http://sigdeletras.com/2021/geoapuntes1-presentacion-mapa-solar-fotogramas-geospatial-data-science-simbolog%C3%ADa-y-api-key/"> + Información sobre GEOApuntes</a></p>Patricio Soriano Castropasoriano@sigdeletras.comRECURSOS: Imagen de GeoServer de Geomatico Enlace: https://geomatico.es/en/100k-pulls-of-our-docker-geoserver/ Fuente: Linkedin Contad en una empresa tecnológica con una persona que maneje de forma avanzada Docker es sin duda un valor añadido. Llevo aproximadamente tres trabajando con imágenes y contenedores Docker pero a nivel de usuario. Pero saber montar una imagen o crear correctamente un contenedor que tiren de varias imágenes, que esté correctamente parametrizado, gestiona correctamente volúmenes de datos y ya que decir que pueda ser desplegado en producción es harina de otro costal. Para los que nos movemos a nivel básico es preferible aprovecharse de los que realmente saben hacer las cosas. Esta es la razón por es interesante aprovechar la imagen de GeoServer gestionada por la Óscar Fonts de Geomatico.com merece la pena ser guardada en este GEOApuntes. Sumo a favoritos el repositorio de imágenes de Postgres/PostGIS en GitHub de la gente de (la antigua) Geographica por si alguien está interesado. PROGRAMACIÓN: Aprendizaje-Servicio en el desarrollo de software Enlace: https://us2.campaign-archive.com/?u=374c664073e1a1fa3deca53b4&id=5f38e5523a Fuente: Lista de correos Los domingos llega a mi correo La Bonilista de David Bonilla. Me gusta sacar un rato para leer los artículos sobre el sector y la industria tecnológica. Los textos me son bastante atractivos tanto por la temático como por el estilo con el que son escritos. El pasado 29 de agosto, guarde en la lista de Notion el artículo de Raúl Recacha titulado “Aprendizaje-Servicio en el desarrollo de software” en que se explica qué son los proyectos aprendizaje-servicio en relación con aquellos proyectos o iniciativas enfocadas en aprender una nueva habilidad tecnológica (lenguaje, framework…) pero haciendo un servicio a la comunidad. Esto me ha hecho pensar la gran cantidad de tiempo que he dedico a aprender o mejorar mi capacidad de alguna herramienta tecnológica vinculada con la información geográfica. Quizás parte de estas horas podrían ser de más utilidad eligiendo una temática de interés general, con un beneficio social o de utilidad para alguna comunidad o asociación. Echo de menor las actividades de voluntariado que organizábamos en Geoinquietos Córdoba como los proyectos para HOT, el mapeado se infraestructuras de bicicetas, ediciones para mejorar OpenStreetMap y la utilidad que estas podrían tener al menos a nivel local. CASOS DE USO: SIG para la evaluación y valoración de los espacios verdes públicos municipales. Enlace: https://www.europapress.es/cantabria/noticia-torrelavega-tiene-superficie-verde-relativamente-importante-distribucion-espacios-desequilibrada-20210412130511.html Fuente: Prensa He dejado marcado este Trabajo de Fin de grado realizado por Darío Puente en el que evalúa y valora los espacios verdes municipales de Torrelavega y que según vi en la noticia (pasada) va a ser usado por el Ayuntamiento para equilibrar la distribución de suelo público dedicado a espacios verdes. Por mi relación profesional pasada con la gestión municipal a nivel técnico, siempre estoy atento a ejemplos de aplicación de los SIG a aspecto relativos al análisis y diagnóstico de lo urbano. Según leo se han analizado aspectos relativos a la fragmentación y discontinuidad en la ubicación de las áreas verdes, o la ratio de espacios verdes por habitante. El TFG está disponible en el repositorio de la Universidad de Cantabria RECURSOS: Caracterización y distribución del espacio construido en Andalucía. Enlace: Varios Fuente: Lista de correos El Instituto de Estadística y Cartografía de Andalucía está generando una serie de mallas estadísticas de 250m x 250m para su descarga (shape) o acceso mediante WMS/WFS relativas distintos aspectos vinculados con la caracterización y distribución del parque de edificios construidos en Andalucía a partir de Catastro Inmobiliario. Por ahora pueden consultarse: Distribución Espacial de las Tipologías Constructivas Catastrales Edificios (mediana del año de antigüedad, total de edificios nº de plantas, usos principales) Viviendas (mediana del año de antigüedad, nº de viviendas, superficie, colectivas, unifamiliares, edificación rural). Tener todos estos datos al alcance de un clic, teniendo siempre claro el nivel de desagraguegación de los datos está realemente bien. Para todo lo demás…Catastro. Mercator mediante, la semana que viene más…🌍 + Información sobre GEOApuntes#GEOApuntes 2: git-extras, bboxfinder, data-glossary y SIU2021-08-23T00:00:00+00:002021-08-23T00:00:00+00:00https://sigdeletras.com/2021/geoapuntes2-git-extras-bboxfinder-siu-y-data-glossary<h2 id="gestión-de-proyectos-git-extras">GESTIÓN DE PROYECTOS. Git-extras</h2>
<p><a href="https://git-scm.com/">Git</a>, como herramienta de gestión de versiones, es un herramienta que cualquier profesional que realice desarrollo debe conocer. Uso Git, de forma combinada con <a href="https://github.com/sigdeletras">GitHub</a>, tanto en proyectos personales como dentro del trabajo.</p>
<p>Las funcionalidades básicas se aprenden rápido. Hay gran cantidad de recursos para ello. Pero si se quiere definir unas directrices claras en su uso a nivel profesional es necesario acceder a contenidos más avanzados.</p>
<p>En esta línea, la semana pasada terminé el curso <em>Git: Introducción y trabajo en equipo</em> de la mano de la gente de <a href="https://pro.codely.tv/library/">CodelyTV Pro</a>.</p>
<p>Dentro de la cantidad de recursos que ofrecen comparto el repositorio <a href="https://github.com/tj/git-extras">git-extras</a> un conjunto de alias pensados que va a permitir obtener informaciones estadísticas, analizar el tiempo y “esfuerzo” a un repositorio en base al número de commits, crear nuevos alias, crear un archivo gitignore…</p>
<h2 id="recursos-bboxfinder">RECURSOS. Bboxfinder</h2>
<p>Es muy frecuente que si estamos desarrollando un visor de mapas web con cualquiera de las librerías existentes que necesitemos obtener una las coordenadas delimitadoras (bounding box o bbox) de una determinada área geográfica. En el blog de la empresa, mi compañera Eva Rabasco hizo una entrada haciendo un resumen sobre <a href="https://geoinnova.org/blog-territorio/librerias-js-mas-populares-para-datos-geolocalizados-y-mapas/">librerías de <em>webmapping</em></a> que merece tener guardada en favoritos.</p>
<p>La aplicación web <a href="http://bboxfinder.com/">bboxfinder</a> desarrollada por Aaron Racicot es una herramienta de gran ayuda para obtener esta información.</p>
<p>Aunque creo que hace falta darle una vuelta a la interfaz, tiene opciones tan interesantes como la selección del sistema de coordenadas de referencia, la opción de presentarlas en Longitud/Latitud o al revés, coordenadas del centro en distintos sistemas de coordenadas de referencias.</p>
<h2 id="recursos-data-glossary">RECURSOS. Data-glossary</h2>
<p><a href="https://www.linkedin.com/in/ramiroaznar/">Ramiro Aznar</a>, Senior Geospatial Data Engineer en Planet ha compartido un interesante <a href="https://github.com/ramiroaznar/data-glossary">repositorio en GitHub con palabras y términos en inglés relacionados con los datos</a>.</p>
<p>Según comentó en Linkedin y en el mismo repositorio “la mayoría de las referencias utilizadas en este glosario provienen de Wikipedia y los primeros resultados de búsqueda en Google”.</p>
<p>Es una un trabajo en proceso y abierto a sugerencias y aportes. Como comentario a su publicación en Linkedin, he indicado que sería interesante contar con las referencias. Esto tendría gran utilidad por ejemplo para realizar un folk del repositorio y añadir versiones en otros idiomas del glosario.</p>
<p>…acabo de revisar el repositorio y ya están los enlaces a Wikipedia.</p>
<p>Muchas gracias a Ramiro por la recopilación y por compartir.</p>
<h2 id="casos-de-uso-siu-sistema-de-información-urbana">CASOS DE USO. SIU Sistema de Información Urbana</h2>
<p>Esta semana he necesitado realizar trabajar con capas a nivel autonómico relativas a ordenación del territorio y urbanismo. En este campo, cada comunidad autónoma tiene su propia legislación y normativa y según el caso, la información geográfica puede estar accesible desde los geoportales o las IDEs autonómicas a modo de servicios de descarga o WMS.</p>
<p>Me parece por lo tanto un esfuerzo a resaltar, el trabajo y la información ofrecida en el portal del <a href="https://www.mitma.gob.es/portal-del-suelo-y-politicas-urbanas/sistema-de-informacion-urbana/sistema-de-informacion-urbana-siu">Sistema de Información Urbana (SIU)</a> del Ministerio de Transportes, Movilidad y Agenda Urbana.</p>
<p>En su página informativa se indica como objetivo base el de promover la transparencia en materia de suelo y urbanismo en España en la que es clave la colaboración y coordinación con las Comunidades Autónomas.</p>
<p>Desde el <a href="https://mapas.fomento.gob.es/VisorSIU/">visor</a> accederemos a las capas información urbanística como la clasificación del suelo, el grado de desarrollo, el planeamiento vigente, datos del CORINE o el SIOSE o información de apoyo como el Catastro.</p>
<p>Me ha sorprendido las fechas de actualización. Por ejemplo, para el caso del PGOU de Córdoba aprobado en el 2001, la fecha de actualización es de diciembre del 2020.
La información es exportable en varios formatos como por ejemplo CSV y GeoJSON.</p>
<p>Mercator mediante, la semana que viene más…🌍</p>
<p><a href="http://sigdeletras.com/2021/geoapuntes1-presentacion-mapa-solar-fotogramas-geospatial-data-science-simbolog%C3%ADa-y-api-key/"> + Información sobre GEOApuntes</a></p>Patricio Soriano Castropasoriano@sigdeletras.comGESTIÓN DE PROYECTOS. Git-extras Git, como herramienta de gestión de versiones, es un herramienta que cualquier profesional que realice desarrollo debe conocer. Uso Git, de forma combinada con GitHub, tanto en proyectos personales como dentro del trabajo. Las funcionalidades básicas se aprenden rápido. Hay gran cantidad de recursos para ello. Pero si se quiere definir unas directrices claras en su uso a nivel profesional es necesario acceder a contenidos más avanzados. En esta línea, la semana pasada terminé el curso Git: Introducción y trabajo en equipo de la mano de la gente de CodelyTV Pro. Dentro de la cantidad de recursos que ofrecen comparto el repositorio git-extras un conjunto de alias pensados que va a permitir obtener informaciones estadísticas, analizar el tiempo y “esfuerzo” a un repositorio en base al número de commits, crear nuevos alias, crear un archivo gitignore… RECURSOS. Bboxfinder Es muy frecuente que si estamos desarrollando un visor de mapas web con cualquiera de las librerías existentes que necesitemos obtener una las coordenadas delimitadoras (bounding box o bbox) de una determinada área geográfica. En el blog de la empresa, mi compañera Eva Rabasco hizo una entrada haciendo un resumen sobre librerías de webmapping que merece tener guardada en favoritos. La aplicación web bboxfinder desarrollada por Aaron Racicot es una herramienta de gran ayuda para obtener esta información. Aunque creo que hace falta darle una vuelta a la interfaz, tiene opciones tan interesantes como la selección del sistema de coordenadas de referencia, la opción de presentarlas en Longitud/Latitud o al revés, coordenadas del centro en distintos sistemas de coordenadas de referencias. RECURSOS. Data-glossary Ramiro Aznar, Senior Geospatial Data Engineer en Planet ha compartido un interesante repositorio en GitHub con palabras y términos en inglés relacionados con los datos. Según comentó en Linkedin y en el mismo repositorio “la mayoría de las referencias utilizadas en este glosario provienen de Wikipedia y los primeros resultados de búsqueda en Google”. Es una un trabajo en proceso y abierto a sugerencias y aportes. Como comentario a su publicación en Linkedin, he indicado que sería interesante contar con las referencias. Esto tendría gran utilidad por ejemplo para realizar un folk del repositorio y añadir versiones en otros idiomas del glosario. …acabo de revisar el repositorio y ya están los enlaces a Wikipedia. Muchas gracias a Ramiro por la recopilación y por compartir. CASOS DE USO. SIU Sistema de Información Urbana Esta semana he necesitado realizar trabajar con capas a nivel autonómico relativas a ordenación del territorio y urbanismo. En este campo, cada comunidad autónoma tiene su propia legislación y normativa y según el caso, la información geográfica puede estar accesible desde los geoportales o las IDEs autonómicas a modo de servicios de descarga o WMS. Me parece por lo tanto un esfuerzo a resaltar, el trabajo y la información ofrecida en el portal del Sistema de Información Urbana (SIU) del Ministerio de Transportes, Movilidad y Agenda Urbana. En su página informativa se indica como objetivo base el de promover la transparencia en materia de suelo y urbanismo en España en la que es clave la colaboración y coordinación con las Comunidades Autónomas. Desde el visor accederemos a las capas información urbanística como la clasificación del suelo, el grado de desarrollo, el planeamiento vigente, datos del CORINE o el SIOSE o información de apoyo como el Catastro. Me ha sorprendido las fechas de actualización. Por ejemplo, para el caso del PGOU de Córdoba aprobado en el 2001, la fecha de actualización es de diciembre del 2020. La información es exportable en varios formatos como por ejemplo CSV y GeoJSON. Mercator mediante, la semana que viene más…🌍 + Información sobre GEOApuntes#GEOApuntes 1: presentación, mapa solar, fotogramas, geospatial data science, simbología y api key2021-08-15T00:00:00+00:002021-08-15T00:00:00+00:00https://sigdeletras.com/2021/geoapuntes1-presentacion-mapa%20solar-fotogramas-geospatial-data-science-simbolog%C3%ADa-y-api-key<p><strong>GEOApuntes</strong> pretende ser un conjunto de entradas con periodicidad semanal en las que se iré dejando mis comentarios y notas sobre determinados recursos, entradas y enlaces relacionados con el campo de las geotecnologías.</p>
<!--more-->
<p>El objetivo principal de estas notas no es otro de <strong>localizar, filtrar, modificar y distribuir, de forma segmentada, aquella información del ámbito de las tecnologías de información geográfica</strong> procedentes de mis redes sociales (<a href="https://www.linkedin.com/in/patriciosorianocastro/">Linkedin</a> y <a href="https://twitter.com/sigdeletras">Twitter</a>) que me ha resultado de interés.</p>
<p>Personalmente, veo interesante poder disponer de una especie de bloc de notas al que poder recurrir de forma rápida. Suelo hacerlo en <a href="https://github.com/sigdeletras">GitHub</a> cuando preparo documentación para nuevos proyectos o recopilo enlaces para futuros curso, charlas o artículos.</p>
<p>La idea principal es compartir 4 o 5 apuntes relacionados con ámbitos a los que me dedico profesionalmente:</p>
<ul>
<li><strong>SIG</strong>: Novedades sobre Sistemas de Información Geográfica.</li>
<li><strong>PROGRAMACIÓN</strong>. Recursos, entradas, código sobre programación en el campo geo (Python y JavaScript).</li>
<li><strong>GESTIÓN DE PROYECTOS</strong>: Experiencias, metodologías y bases para la gestión de proyectos relacionados con las geotecnologías y el análisis territorial.</li>
<li><strong>CASOS DE USO</strong>. Cada día se conoce una nueva aplicación de las tecnologías de información geográfica en multitud de nuevos campos.</li>
<li><strong>RECURSOS</strong>. Fuentes de datos y recursos geográficos que merecen la pena tener a mano.</li>
</ul>
<p>Para estar verdaderamente informado de forma semanal sobre las novedades del sector de las geotecnologías recomiendo mucho la suscripción a los <a href="https://www.nosolosig.com/47-boletines-nosolosig">Boletines de NosoloSIG</a> o la recopilación de enlaces casi diarios de las <a href="https://geoinquiets.github.io/rafagas/">Ráfagas</a> de <a href="https://www.linkedin.com/in/rafael-roset-910b947/?originalSubdomain=es">Raf Roset</a> que recopila Jorge Sanz <a href="https://twitter.com/xurxosanz">@xurxosanz</a> (…la idea del título de GEOApuntes la he copiado de aquí)</p>
<p>Si creéis que tenéis un caso de uso o experiencia sobre algunos de estos temas que pueda encajar en alguna de estas temáticas, solo tenéis que comentarlo. Me comprometo al menos en darle una vuelta, y si cuadra con la filosofía de GEOApuntes añadirlo.</p>
<h2 id="casos-de-uso-mapa-solar-para-análisis-del-autoconsumo-de-la-ciudad-de-murcia">CASOS DE USO: Mapa solar para análisis del autoconsumo de la ciudad de Murcia</h2>
<ul>
<li>Enlace: <a href="https://www.eseficiencia.es/2021/07/19/mapa-solar-herramientas-gis-analizara-potencial-autoconsumo-ciudad-murcia">https://www.eseficiencia.es/2021/07/19/mapa-solar-herramientas-gis-analizara-potencial-autoconsumo-ciudad-murcia</a></li>
<li>Fuente: Linkedin</li>
</ul>
<p>Guardé esta noticia como ejemplo de un caso de uso de aplicación de los <strong>GIS como herramienta para analizar el potencial de autoconsumo y producción de energía fotovoltaica</strong> y térmica del municipio de Murcia.</p>
<p>Me pareció interesante el uso de datos abiertos como Catastro, la exposición de funciones básicas de un SIG como el “solapamiento de capas”, todo pensado para la estimación del potencial de producción eléctrica mensual y anual.</p>
<p>Al final del artículo se habla sobre la localización de edificios públicos donde poder instalar sistemas fotovoltaicos. Leyendo esto me acordé de magnífico trabajo del equipo del <strong>SIG de Cáceres</strong> y como hace unos años habían presentado un <a href="https://sig.caceres.es/potencial_solar_fotovoltaico/">visor web</a> como resultado de un trabajo junto a la Universidad de Extremadura sobre el Potencial Solar Fotovoltaico de las Cubiertas en la Ciudad de Cáceres.</p>
<p>Al mover a entrada por Linkedin, <a href="https://www.linkedin.com/in/josecrespocadorniga/">José Crespo</a> CTO en DOTGIS compartió el enlace de SolarMap, una aplicación SasS para calcular el potencial solar en azoteas que utiliza de nuevo datos abiertos, información LiDAR, análisis Big Data y tecnologías de Machine Learning.</p>
<h2 id="recursos-fechas-y-certificaciones-de-fotogramas-del-cnig">RECURSOS. Fechas y certificaciones de fotogramas del CNIG</h2>
<ul>
<li>Enlace: <a href="https://fototeca.cnig.es/fototeca/">https://fototeca.cnig.es/fototeca/</a></li>
<li>Fuente: Grupo Telegram de Geoinquietos Córdoba</li>
</ul>
<p>En el grupo de <a href="https://wiki.osgeo.org/wiki/Category:Geoinquietos_C%C3%B3rdoba">Geoinquietos Córdoba</a>, se lanzó una consulta sobre cómo conocer de forma exacta la fecha de un fotograma del <a href="https://datos.gob.es/es/catalogo/e00125901-spaignvuelointerministerial">Vuelo de 1973-1986 Interministerial</a>. La cuestión era de interés por el uso de este tipo de recursos para tema de legalización de edificaciones en suelo no urbanizable.</p>
<p>La solución la compartió al final <a href="https://twitter.com/jcricocordoba?lang=es">José Carlos Rico</a> de CityLab360, comentado en el nuevo <a href="https://fototeca.cnig.es/fototeca/">visor de la Fototeca Digital</a> permite acceder a este dato. y además, que el propio CNIG tiene un servicio de certificación y digitalización de fotogramas de la Fototeca.</p>
<p>Comparto de paso un <a href="https://blog-idee.blogspot.com/2021/08/nueva-fototeca-digital.html">artículo reciente del Blog de la IDEE</a> hablando sobre La Fototeca Digital del Centro Nacional de Información Geográfica.</p>
<h2 id="gestión-de-proyectos-geospatial-data-science-vs-gis">GESTIÓN DE PROYECTOS. Geospatial Data Science vs GIS</h2>
<ul>
<li>Enlace: <a href="http://millermountain.com/geospatialblog/2021/07/29/geospatial-data-science-vs-gis/">http://millermountain.com/geospatialblog/2021/07/29/geospatial-data-science-vs-gis/</a></li>
<li>Fuente: Linkedin</li>
</ul>
<p>El perfil de Data Scientist o Científico de Datos es uno los puestos que más auge está teniendo actualmente. Este tipo de profesionales son igualmente solicitados por empresa que trabajan con la componente espacial de la información.</p>
<p>En este artículo en inglés del consultor GIS Mike Miller (<a href="https://twitter.com/millermountainl">@millermountainl</a>) se hace una interesante reflexión sobre las <strong>diferencias entre un analista GIS y un científico de datos geoespaciales</strong> haciendo referencia al peso de los conocimientos sobre estadística y matemáticas en este último.</p>
<p>Me quedo también con la última parte del artículo en la que se hace una relación de la pila de recursos y conocimientos de base para poder dedicarse a este campo como Bases de Datos Geo o Python con librerías como GeoPandas o Matplotlib.</p>
<p>Por cierto, llego un tiempo haciendo scripts con librerías Geo de Python como <a href="https://geopandas.org/">GeoPandas</a> y el tema de la ciencia de datos no es mi especialidad, solo comentar que estoy realmente encantado.</p>
<h2 id="recursos-recopilación-de-simbología-para-mapas-temáticos-de-qgis">RECURSOS: Recopilación de simbología para mapas temáticos de QGIS</h2>
<ul>
<li>Enlace: <a href="https://github.com/qgispe/Symbology-Hub">https://github.com/qgispe/Symbology-Hub</a></li>
<li>Fuente: Twitter</li>
</ul>
<p>Repositorio en GitHub del <a href="https://www.facebook.com/groups/555283231765808/">Grupo Oficial de usuarios QGIS Perú</a> con conjunto de simbologías puntuales por temáticas (agricultura, arqueología, ecología…).</p>
<p>Suelo compartir con mis alumnos la página de <a href="http://qgis-hub.fast-page.org/?i=1">QGIS Hub</a> de Klas Karlsson https://twitter.com/klaskarlsson que además de simbología contiene plantillas para composiciones.</p>
<h2 id="sig-cómo-crear-una-cuenta-y-una-api-key-con-arcgis-platform">SIG: Cómo crear una cuenta y una API key con ArcGIS Platform</h2>
<ul>
<li>Enlace: <a href="https://www.youtube.com/watch?v=C69d1ao5xK4">https://www.youtube.com/watch?v=C69d1ao5xK4</a></li>
<li>Fuente: Canal Discord de GeoDevelopers</li>
</ul>
<p>En este vídeo de <a href="https://www.linkedin.com/in/libertadchapinalcervantes/?originalSubdomain=es">Libertad Chapinal</a> (<a href="https://twitter.com/LibertadChC">@LibertadChC</a>) cuenta como cómo crear una cuenta y una API key con ArcGIS Platform.</p>
<p>Se agradecen este tipo de vídeos ya que la información y recursos sobre estos temas en muy amplia en la documentación oficial y la ingente cantidad de aplicaciones que tiene ESRI. Estas guías son por tanto muy interesantes para neófitos en la materia.</p>
<p>Hago de paso referencia al <a href="https://www.geodevelopers.org/">grupo de GeoDevelopers</a>, en cuyo canal está subido este vídeo. Desde que trabajo en remoto, y con todo esto de la pandemia, suelo pasarme cuando puedo por el coworking virtual que se ha montado y que te permite estar en contacto profesionales del ámbito geo.</p>
<p>Mercator mediante, la semana que viene más…🌍</p>Patricio Soriano Castropasoriano@sigdeletras.comGEOApuntes pretende ser un conjunto de entradas con periodicidad semanal en las que se iré dejando mis comentarios y notas sobre determinados recursos, entradas y enlaces relacionados con el campo de las geotecnologías.Instalación de librerías geoespaciales en Python. ¿Pip o Conda?2021-07-11T00:00:00+00:002021-07-11T00:00:00+00:00https://sigdeletras.com/2021/instalacion-de-librerias-geoespaciales-en-python-pip-o-conda<p>Python, junto a R, es uno de los lenguajes de uso más frecuente en el ámbito SIG. Este lenguaje de programación suele ser la primera opción para comenzar a programas de aquellas personas que trabajan en el ámbito del análisis geoespacial.
<!--more--></p>
<p>Entre las razones de esta elección, además de su rápida curva de aprendizaje, se encuentra su integración como lenguaje de scripting en SIG de escritorio tan conocidos como QGIS o ArcGIS.</p>
<p>Pero el uso de Python en el campo de las geotecnologías no se limita explotación dentro de un SIG. Gracias a la cantidad de librerías existentes (ej. GDAL/OGR, Geopandas, Shapely, Rasterio, Fiona, PyProj, Numpy, Pandas, Scipy Matplotlib…) podemos obviar la interfaz gráfica que nos ofrecen los SIG y trabajar directamente con los datos espaciales para su consulta, edición y análisis.</p>
<p>La facilidad de acceso a grandes volúmenes de datos y el auge de las tecnologías y salidas profesionales (<em>data scientist</em>) relacionadas con el aprendizaje automático, la visualización de datos, el procesamiento de imágenes o el procesamiento ETL en el que se incluye el dato geográfico está provocando un acercamiento aún mayor a Python.</p>
<p>Dejando aparte el interés y las razones del uso de Python en ámbito profesional geo, <strong>el aprendizaje de un nuevo lenguaje informático pasa siempre por su instalación</strong>.</p>
<p>En la siguiente entrada voy a dejar comentados algunos <strong>aspectos para tener en cuenta si queremos empezar a manejar Python y sus librerías SIG</strong>.</p>
<h2 id="instalación-de-python">Instalación de Python</h2>
<p>Python se encuentra preinstalado en máquinas con GNU/Linux. Abriendo una consola de comandos y escribiendo python o python3 nuestro equipo está preparado para empezar a programar.</p>
<p>Para equipos con Windows tenemos que realizar la descarga de los instaladores según la arquitectura de nuestro equipo desde web de Python <a href="https://www.python.org/">https://www.python.org/</a> y proceder a su instalación.</p>
<p><img src="/images/blog/202107-pip-conda/00_python_hellworld.jpg" alt="Hello World Python" /></p>
<p>No trabajo con MacOS, pero según leo, creo que viene preinstalado Python 2.7 por lo que será también necesario realizar la instalación a Python 3.</p>
<h2 id="paquetes-y-entornos-virtuales">Paquetes y entornos virtuales.</h2>
<p>Al instalar Python en nuestro equipo tenemos disponibles por defecto un conjunto de módulos y paquetes destinados a cubrir las operaciones más comunes de la programación diaria.</p>
<p>A estos paquetes o librerías se suman sin embargo otros módulos desarrollados por la comunidad de programadores de Python. La mayoría de ellos se encuentran alojados en el <a href="https://pypi.org/">repositorio de software PyPI</a>.</p>
<p><img src="/images/blog/202107-pip-conda/01_pypi_gdal.jpg" alt="Pypi" /></p>
<p>Para instalar un módulo, utilizaremos el <a href="https://es.wikipedia.org/wiki/Pip_(administrador_de_paquetes)">administrador de paquetes Python pip</a> usando el comando <em>install</em>.</p>
<p>En el siguiente comando se instalaría de forma global la librería <a href="https://rasterio.readthedocs.io/en/latest/">rasterio</a> para el trabajo de archivos ráster.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install rasterio
</code></pre></div></div>
<p>Hasta ahora parece todo muy sencillo. Pero hay que tener en consideración varios aspectos.</p>
<ul>
<li>Las <strong>librerías tienen versiones y la mayoría de ellas tienen dependencias</strong> a otras librerías. Por ejemplo, para usar el paquete de tratamiento de datos espaciales <a href="https://geopandas.org/">Geopandas</a> deberemos tener instalado también en nuestro equipo las versiones correctas de numpy, pandas, shapely, fiona y pyproj.</li>
<li>Si hacemos una instalación de forma global <strong>solo podremos tener una versión concreta instalada de un determinado módulo</strong>*</li>
</ul>
<p>Para dar solución a estos aspectos es recomendable el uso de <strong>entornos virtuales</strong>.</p>
<p>Un entorno es un espacio donde instalará los paquetes necesarios para el desarrollo de un determinado proyecto. El uso de entorno solucionará el tema de los requisitos y dependencias y permitirá la elección de las versiones que necesitemos.</p>
<p>Con pip, podemos instalar <em>venv</em> o <em>virtualenv</em> que van a darnos la opción de crear entornos virtuales.</p>
<p>En el siguiente código creamos con <em>venv</em> un entorno que llamaremos ‘geoenv’, lo activamos e instalamos la librería <a href="https://pypi.org/project/Shapely/">Shapely</a>.</p>
<p><img src="/images/blog/202107-pip-conda/02_venv.jpg" alt="Creación de entorno virtual con venv" /></p>
<h2 id="conda-y-anaconda-al-rescate">Conda y Anaconda al rescate</h2>
<p>Aunque pip es una magnífica herramienta para instalar paquetes, en algunas ocasiones, debido a las dependencias, <strong>las instalaciones no son exitosas</strong>. Instalar por ejemplo el paquete GDAL o Geopandas es un auténtico quebradero de cabeza.</p>
<p><img src="/images/blog/202107-pip-conda/03_error_geopandas.jpg" alt="Error a instalar geopandas con Pip" /></p>
<p>Es aquí donde Anaconda y el instalador Conda vienen al rescate.</p>
<p><a href="https://www.anaconda.com/">Anaconda</a> es una <em>suite</em> de código abierto multiplataforma que abarca una serie de aplicaciones, librerías y conceptos diseñados para el desarrollo de la ciencia de datos con Python y R.</p>
<p>Cuando instalamos Anaconda en nuestro equipo, además de contar con Python y R, tendremos un administrador de entornos, una interfaz gráfica de usuario (Anaconda Navigator) y un sinfín de librerías preinstaladas.</p>
<p>Anaconda dispone de su <strong>propio administrador de paquetes</strong> propio llamado <strong>Conda</strong>. Con Conda gestioanamos los entornos e instalamos o actualizamos los paquetes desde el repositorio de Anaconda.</p>
<p>Los paquetes de Conda son binarios, por lo que no es necesario tener compiladores para instalarlos. Esto es una de las grandes ventajas respecto a pip y en la que muchas veces tropezamos al instalar nuestros módulos.</p>
<p><img src="/images/blog/202107-pip-conda/comparación_conda_pip.jpg" alt="Comparación Conda vs Pip" />
<em>Fuente: Anaconda web</em></p>
<p>Si nos decantamos por la <a href="https://www.anaconda.com/products/individual">instalación de Anaconda</a> podemos usar la interfaz gráfica de Anaconda Navigator para crear e instalar paquetes o bien usar el terminal Anaconda Promt (Windows) o directamente el terminal (Linux y macOS) para las gestiones.</p>
<p><img src="/images/blog/202107-pip-conda/anaconda_navigator.png" alt="Anaconda Navigator " /></p>
<h2 id="miniconda">Miniconda</h2>
<p>Instalar <strong>Anaconda</strong> nos va a permitir trabajar sin problemas en nuestros proyectos de Python y realizar las correspondientes tareas de administración y gestión. Pero tenemos un pequeño inconveniente. Esta <strong>gran disponibilidad de recursos</strong> ocupa aproximadamente 3GB.</p>
<p>Como alternativa a Anaconda, con un peso mucho menor (400 MB) y con una instalación limitada a los imprescindible tenemos <a href="https://docs.conda.io/en/latest/miniconda.html">Miniconda</a> que instalará el gestor Conda y a sus dependencias.</p>
<p>En mi opinión prefiero tener controlado los paquetes que uso en cada proyecto, por lo que me decanto por Miniconda.</p>
<h2 id="un-ejemplo-de-trabajo-con-datos-ráster-con-conda">Un ejemplo de trabajo con datos ráster con Conda</h2>
<p>Voy a mostrar continuación un breve guion de gestión de un <strong>proyecto Python con Conda para trabajar con un archivo de modelos digital de elevaciones</strong> del IGN.</p>
<p>Nuestro proyecto va a requerir la instalación de las siguientes librerías:</p>
<ul>
<li>Rasterio</li>
<li><a href="https://matplotlib.org/">Matplotlib</a> para el ploteo del archivo</li>
</ul>
<p>Usaremos como entorno interactivo para trabajar <a href="https://jupyter.org/">Jupiter Lab</a>.</p>
<ol>
<li>Tras instalar Miniconda lo primer que debemos hacer es crear un <em>enviroment</em> y activarlo.</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>conda create --name geoenv
conda activate geoenv
</code></pre></div></div>
<ol>
<li>El siguiente paso será la instalación de las librerías.</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>conda install rasterio matplotlib
</code></pre></div></div>
<ol>
<li>Y necesitaremos también Jupiter Lab pero usando el repositorio <a href="https://conda-forge.org/">conda-forge</a></li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>conda install -c conda-forge jupyterlab
</code></pre></div></div>
<ol>
<li>Tras las instalaciones lanzaremos Jupiter y ya tendremos todo listo para ir creando nuestro código Python.</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>jupyter lab
</code></pre></div></div>
<p>La siguiente captura muestra un código muy sencillo para comenzar nuestro proyecto de visualización de un MDE en Python.</p>
<p><img src="/images/blog/202107-pip-conda/04_jupiter.jpg" alt="Anaconda Navigator " /></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">rasterio</span>
<span class="kn">from</span> <span class="nn">matplotlib</span> <span class="kn">import</span> <span class="n">pyplot</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">rasterio</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"data/PNOA_MDT25_ETRS89_HU30_0923_LID.asc"</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="s">'-------Metadatos-------------'</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="s">'Formato de datos:'</span><span class="p">,</span> <span class="n">data</span><span class="p">.</span><span class="n">driver</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Número de bandas: </span><span class="si">{</span><span class="n">data</span><span class="p">.</span><span class="n">count</span><span class="si">}</span><span class="s"> '</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Ancho de imagen: </span><span class="si">{</span><span class="n">data</span><span class="p">.</span><span class="n">width</span><span class="si">}</span><span class="s"> '</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Altura de imagen: </span><span class="si">{</span><span class="n">data</span><span class="p">.</span><span class="n">height</span><span class="si">}</span><span class="s"> '</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Rango geográfico: </span><span class="si">{</span><span class="n">data</span><span class="p">.</span><span class="n">bounds</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="s">'-------Estadísticas-------------'</span><span class="p">)</span>
<span class="n">band1</span> <span class="o">=</span> <span class="n">data</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Elevación máxima: </span><span class="si">{</span><span class="n">band1</span><span class="p">.</span><span class="nb">max</span> <span class="p">()</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Elevación mímina: </span><span class="si">{</span><span class="n">band1</span><span class="p">.</span><span class="nb">min</span> <span class="p">()</span><span class="si">}</span><span class="s"> '</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="sa">f</span><span class="s">'Media: </span><span class="si">{</span><span class="n">band1</span><span class="p">.</span><span class="n">mean</span> <span class="p">()</span><span class="si">}</span><span class="s">'</span><span class="p">)</span>
<span class="n">pyplot</span><span class="p">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="n">cmap</span><span class="o">=</span><span class="s">'pink'</span><span class="p">)</span>
<span class="n">pyplot</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>
<p>Como hemos podido apreciar comenzar a usar Python sin la ayuda de un Sistema de Información Geográfica no es realmente complicado. El campo de aplicación y las aplicaciones para el análisis geográfico es enorme.</p>Patricio Soriano Castropasoriano@sigdeletras.comPython, junto a R, es uno de los lenguajes de uso más frecuente en el ámbito SIG. Este lenguaje de programación suele ser la primera opción para comenzar a programas de aquellas personas que trabajan en el ámbito del análisis geoespacial.Desinstalación de OSGeo4W… e instalación de la versión 2 de OSGeo4W2021-06-26T00:00:00+00:002021-06-26T00:00:00+00:00https://sigdeletras.com/2021/desinstalacion-de-osgeo4w<p><a href="https://trac.osgeo.org/OSGeo4W/">OSGeo4W</a> es un instalador para el sistema operativo Windows mantenido por la <a href="https://www.osgeo.org/">Open Source Geospatial Foundation</a> que permite, entre otras cuestiones, tener una gestión avanzada de la instalación del Sistema de Información Geográfica de Código Abierto QGIS.</p>
<p>Además de QGIS, el programa permite la instalación de los SIG GRASS y SAGA, la librería GDAL/OGR y más de <a href="https://trac.osgeo.org/OSGeo4W/wiki/PackageListing">150 paquetes geomáticos</a>.</p>
<p><img src="/images/blog/202106_osgeo4w/00_osgeo4w-logo.png" alt="IMG OSGeo4W" /></p>
<p>En mi caso, utilizo OSGeo4W para instalar QGIS porque me permite contar con versiones concretas de QGIS tanto de su lanzamiento RC (Release Candidate) como LTR (Long Term Release).</p>
<p>En el trabajo tenemos desarrollos para clientes en distintas versiones, damos formación avanzada de QGIS basadas en las versiones estables y siempre es interesante ir revisando las novedades de los últimos lanzamientos.</p>
<h2 id="problemas-al-instalar-qgis-320">Problemas al instalar QGIS 3.20</h2>
<p>El pasado 22 de junio, si abrió a la comunidad la versión <a href="https://www.qgis.org/en/site/forusers/visualchangelog320/index.html">QGIS 3.20</a> y me dispuse a instalarla para comenzar a probar las nuevas funcionalidades.</p>
<p>Al lanzar el Setup de OSGeo4W, con la opción avanzada de instalación, e intentar actualizar la versión de QGIS de la 3.18 a la 3.20, cuál fue mi sorpresa 😮 de que esta opción no estaba disponible.</p>
<p><img src="/images/blog/202106_osgeo4w/qgis320.jpg" alt="QGIS 3.20" /></p>
<p>En este momento recorde que en el grupo de Telegram de usuarios de QGIS España, se había comentado que existía una nueva versión de OSGeo4W.</p>
<p>Efectivamente, al entrar en la <a href="https://www.qgis.org/es/site/forusers/download.html">página de descargas de QGIS</a> hay un aviso sobre este tema. En el texto se comenta que existe una nueva versión (OSGeo4W v2) y que requiere dependencias que no se encuentran en el nuevo instalador. Se recomiendo una instalación limpia o usar un directorio diferente.</p>
<p><img src="/images/blog/202106_osgeo4w/02_osgeo4w_v2.jpg" alt="OSGEO4W versión 2" /></p>
<p>Perfecto entonces. Mi opción fue la de descargar la versión nueva e instalarla en un nuevo repositorio. Pero aquí comenzaron los problemas. Siguiendo los pasos normales de instalación empezaron a surgir gran cantidad de errores, surgidos seguramente por la incompatibilidad entre los paquetes, por lo que esta opción no llegó a buen puerto.
Quedaba optar entonces por la segunda opción. Desinstalación de OSGeo4W y de QGIS. Pero… sorpresa, OSGeo4W no cuenta con un desinstalador.</p>
<h2 id="desinstalando-osgeo4w">Desinstalando OSGeo4W</h2>
<p>Parece que suele ser una pregunta recurrente ya que la misma página de OSGeo incluye en sus FAQ la respuesta a <a href="https://trac.osgeo.org/OSGeo4W/wiki/FAQ#IsthereawayofuninstallingpackagesorallofOSGeo4W">cómo podemos desinstalar un paquete del instalador o el mismo desinstalador</a>.</p>
<p><img src="/images/blog/202106_osgeo4w/03_uninstatl.jpg" alt="OSGEO4W versión 2" /></p>
<p>Ya que nuestro objetivo era borrar por completo la antigua versión del setup y todos los paquetes instalados la única opción que nos da es <em>“just delete the whole OSGeo4W file tree (usually C:\OSGeo4W)”</em> 😱</p>
<p>Como sabemos, este tipo de desinstalación puede darnos algunos problemas. Pero tras alguna que otra consulta expongo a continuación los pasos a dar y que en mi caso ha llegado a buen puerto la instalación.</p>
<h3 id="1-copia-de-la-carpeta-de-perfiles">1. Copia de la carpeta de perfiles</h3>
<p>Cuando estamos trabajando <strong>con QGIS toda la configuración personalizada del programa</strong>, las conexiones a bases de datos y servicios OGC, simbología personalizada o incluso los complementos que tengamos instalados quedan <strong>vinculados a un perfil</strong>.</p>
<p>Esto significa que podemos crear tantas configuraciones personalizadas como deseemos. Por poner un ejemplo, recientemente desarrollamos un <a href="https://geoinnova.org/blog-territorio/plugin-qgis-descarga-cartografia-catastral-navarra-geoinnova/">complemento para la descarga del Catastro de la Comunidad Foral de Navarra</a>. El complemento estaba en varios idiomas y para probar que se cargaban correctamente la traducción, generé un nuevo perfil con el euskera como idioma por defecto.</p>
<p>Lo primero que debemos hacer por tanto es realizar una copia de la carpeta profile que se encuentra en <em>C:\Users[nombreusuario]\AppData\Roaming\QGIS\QGIS3</em></p>
<p>Si queremos hacer una instalación limpia podemos borrar esta carpeta, tras realizar una copia de seguridad. Tras la instalación recuperaremos los perfiles que nos sean de interés.</p>
<h3 id="2-eliminación-de-carpetas-y-accesos-directos">2. Eliminación de carpetas y accesos directos</h3>
<p>El siguiente listado recopila las carpetas que he tenido que borrar.</p>
<p>Carpeta raiz de OSGeo4W</p>
<ul>
<li><em>C:\OSGeo4W64</em></li>
</ul>
<p>Carpetas de accesos directos</p>
<ul>
<li><em>C:\ProgramData\Microsoft\Windows\Start Menu\Programs\OSGeo4W</em></li>
<li><em>C:\Users[nombreusuario]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OSGeo4W</em></li>
</ul>
<p>Carpetas de perfiles (opcional)</p>
<ul>
<li><em>C:\Users[nombreusuario]\AppData\Local\QGIS</em></li>
<li>*C:\Users[nombreusuario]\AppData\Roaming\QGIS*</li>
</ul>
<h3 id="3-limpieza-del-registro-de-windows">3. Limpieza del registro de Windows</h3>
<p>Como último paso, es interesante pasar algún programa que nos limpie el registro de Windows. He usado la versión portable del clásico CCleaner.</p>
<h2 id="instalando-qgis-con-osgeo4w-versión-2">Instalando QGIS con OSGeo4W versión 2</h2>
<p>Tenemos ahora el equipo preparado para la nueva instalación de la última versión de OSGeo4W.</p>
<p>Una vez descargada la versión 2 desde la página de QGIS, vamos siguiendo los pasos por defecto de la instalación avanzada.</p>
<p>Como he comentado al principio, me interesa tener instalados los siguientes paquetes:</p>
<ul>
<li>QGIS LTR (3.16)</li>
<li>QGIS RC (3.20)</li>
<li>Plugins de GRASS para QGIS (para ambas versiones)</li>
</ul>
<p>Marco estas opciones y comienza la instalación.</p>
<p><img src="/images/blog/202106_osgeo4w/04_instalacion.jpg" alt="Instalación de QGIS" /></p>
<p>Tras finalizar el proceso de instalación conseguí tener las versiones de QGIS deseadas en mi equipo y listas para poder <strong>seguir dando caña a mi SIG de cabecera</strong> 🤘.</p>
<iframe src="https://giphy.com/embed/xT0GqssRweIhlz209i" width="480" height="320" frameborder="0" class="giphy-embed" allowfullscreen=""></iframe>
<p><a href="https://giphy.com/gifs/breaking-bad-bryan-cranston-i-won-xT0GqssRweIhlz209i">via GIPHY</a></p>Patricio Soriano Castropasoriano@sigdeletras.comOSGeo4W es un instalador para el sistema operativo Windows mantenido por la Open Source Geospatial Foundation que permite, entre otras cuestiones, tener una gestión avanzada de la instalación del Sistema de Información Geográfica de Código Abierto QGIS. Además de QGIS, el programa permite la instalación de los SIG GRASS y SAGA, la librería GDAL/OGR y más de 150 paquetes geomáticos. En mi caso, utilizo OSGeo4W para instalar QGIS porque me permite contar con versiones concretas de QGIS tanto de su lanzamiento RC (Release Candidate) como LTR (Long Term Release). En el trabajo tenemos desarrollos para clientes en distintas versiones, damos formación avanzada de QGIS basadas en las versiones estables y siempre es interesante ir revisando las novedades de los últimos lanzamientos. Problemas al instalar QGIS 3.20 El pasado 22 de junio, si abrió a la comunidad la versión QGIS 3.20 y me dispuse a instalarla para comenzar a probar las nuevas funcionalidades. Al lanzar el Setup de OSGeo4W, con la opción avanzada de instalación, e intentar actualizar la versión de QGIS de la 3.18 a la 3.20, cuál fue mi sorpresa 😮 de que esta opción no estaba disponible. En este momento recorde que en el grupo de Telegram de usuarios de QGIS España, se había comentado que existía una nueva versión de OSGeo4W. Efectivamente, al entrar en la página de descargas de QGIS hay un aviso sobre este tema. En el texto se comenta que existe una nueva versión (OSGeo4W v2) y que requiere dependencias que no se encuentran en el nuevo instalador. Se recomiendo una instalación limpia o usar un directorio diferente. Perfecto entonces. Mi opción fue la de descargar la versión nueva e instalarla en un nuevo repositorio. Pero aquí comenzaron los problemas. Siguiendo los pasos normales de instalación empezaron a surgir gran cantidad de errores, surgidos seguramente por la incompatibilidad entre los paquetes, por lo que esta opción no llegó a buen puerto. Quedaba optar entonces por la segunda opción. Desinstalación de OSGeo4W y de QGIS. Pero… sorpresa, OSGeo4W no cuenta con un desinstalador. Desinstalando OSGeo4W Parece que suele ser una pregunta recurrente ya que la misma página de OSGeo incluye en sus FAQ la respuesta a cómo podemos desinstalar un paquete del instalador o el mismo desinstalador. Ya que nuestro objetivo era borrar por completo la antigua versión del setup y todos los paquetes instalados la única opción que nos da es “just delete the whole OSGeo4W file tree (usually C:\OSGeo4W)” 😱 Como sabemos, este tipo de desinstalación puede darnos algunos problemas. Pero tras alguna que otra consulta expongo a continuación los pasos a dar y que en mi caso ha llegado a buen puerto la instalación. 1. Copia de la carpeta de perfiles Cuando estamos trabajando con QGIS toda la configuración personalizada del programa, las conexiones a bases de datos y servicios OGC, simbología personalizada o incluso los complementos que tengamos instalados quedan vinculados a un perfil. Esto significa que podemos crear tantas configuraciones personalizadas como deseemos. Por poner un ejemplo, recientemente desarrollamos un complemento para la descarga del Catastro de la Comunidad Foral de Navarra. El complemento estaba en varios idiomas y para probar que se cargaban correctamente la traducción, generé un nuevo perfil con el euskera como idioma por defecto. Lo primero que debemos hacer por tanto es realizar una copia de la carpeta profile que se encuentra en C:\Users[nombreusuario]\AppData\Roaming\QGIS\QGIS3 Si queremos hacer una instalación limpia podemos borrar esta carpeta, tras realizar una copia de seguridad. Tras la instalación recuperaremos los perfiles que nos sean de interés. 2. Eliminación de carpetas y accesos directos El siguiente listado recopila las carpetas que he tenido que borrar. Carpeta raiz de OSGeo4W C:\OSGeo4W64 Carpetas de accesos directos C:\ProgramData\Microsoft\Windows\Start Menu\Programs\OSGeo4W C:\Users[nombreusuario]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OSGeo4W Carpetas de perfiles (opcional) C:\Users[nombreusuario]\AppData\Local\QGIS *C:\Users[nombreusuario]\AppData\Roaming\QGIS* 3. Limpieza del registro de Windows Como último paso, es interesante pasar algún programa que nos limpie el registro de Windows. He usado la versión portable del clásico CCleaner. Instalando QGIS con OSGeo4W versión 2 Tenemos ahora el equipo preparado para la nueva instalación de la última versión de OSGeo4W. Una vez descargada la versión 2 desde la página de QGIS, vamos siguiendo los pasos por defecto de la instalación avanzada. Como he comentado al principio, me interesa tener instalados los siguientes paquetes: QGIS LTR (3.16) QGIS RC (3.20) Plugins de GRASS para QGIS (para ambas versiones) Marco estas opciones y comienza la instalación. Tras finalizar el proceso de instalación conseguí tener las versiones de QGIS deseadas en mi equipo y listas para poder seguir dando caña a mi SIG de cabecera 🤘. via GIPHY